Angular NgUpgrade Deploys AngularJS to Angular receive: raw Prompt rejection: unable to read the "get" property from undefined; Zone:

I see a lot of similar problems here, but have not yet found a solution that works. What I THINK is happening because our Ng2App first loads, it does not yet have a link to $ injector, so when I try to use it in the provider declaration (deps: ['$ injector']), it’s not, t exist.

It is extremely strange that I can use this service in Angular COMPONENT, but for some reason I can not use it in the Angular service.

app.js

import UserService from './user.service'; angular.module('app', []) .service('UserService', UserService) .config(/* config */) .run(/* run */); import './ng2app.module'; 

ng2app.module.ts:

 import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; @NgModule({ imports: [ BrowserModule, UpgradeModule, ], declarations: [], entryComponents: [], providers: [ // angularJS service: { provide: 'UserService', useFactory: (i: any) => i.get('UserService'), // <---- this is the line all the errors point to. deps: ['$injector'] }, ] }) export default class Ng2AppModule { constructor(){} } platformBrowserDynamic() .bootstrapModule(Ng2AppModule) .then(platformRef => { const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule; upgrade.bootstrap(document.documentElement, ['app'], {strictDi: true}); }); 

Later ... in service (crash):

 import {Injectable, Inject} from "@angular/core"; import UserService from 'app/login/user.service'; @Injectable() export class AnAngularService{ constructor( // causes the error if I uncomment it wtf: <-------------- // @Inject('UserService') private userService: UserService ){} } 

Later ... in the component (works correctly):

 import { Component } from '@angular/core'; import {Inject} from "@angular/core"; import UserService from 'app/login/user.service'; import template from 'tmpl.html'; @Component({ selector: 'an-angular-component', template, }) export class AnAngularComponent{ constructor( @Inject('UserService') private userService: UserService ){ console.log(userService) // works just fine. wtf <-------------- } } 

Does anyone know why this is happening and how to fix it?

This question is almost exactly the same, but for some reason it did not work

AngularJS Version: 1.5.8
Angular / kernel version and stuff: 4.2.4

Here's a link to the Github issue I opened in the Angular repository

Stacktrace:

 zone.js:522 Unhandled Promise rejection: Cannot read property 'get' of undefined ; Zone: <root> ; Task: Promise.then ; Value: TypeError: Cannot read property 'get' of undefined at useFactory (ng2app.module.ts:114) at _callFactory (core.es5.js:9604) at _createProviderInstance$1 (core.es5.js:9547) at initNgModule (core.es5.js:9498) at new NgModuleRef_ (core.es5.js:10606) at createNgModuleRef (core.es5.js:10590) at Object.debugCreateNgModuleRef [as createNgModuleRef] (core.es5.js:12874) at NgModuleFactory_.create (core.es5.js:13869) at core.es5.js:4556 at ZoneDelegate.invoke (zone.js:334) at Object.onInvoke (core.es5.js:3933) at ZoneDelegate.invoke (zone.js:333) at Zone.run (zone.js:126) at NgZone.run (core.es5.js:3801) at PlatformRef_._bootstrapModuleFactoryWithZone (core.es5.js:4554) at core.es5.js:4596 at ZoneDelegate.invoke (zone.js:334) at Zone.run (zone.js:126) at zone.js:713 at ZoneDelegate.invokeTask (zone.js:367) at Zone.runTask (zone.js:166) at drainMicroTaskQueue (zone.js:546) at <anonymous> TypeError: Cannot read property 'get' of undefined at useFactory (http://localhost:9000/app.bundle.js:4404:52) at _callFactory (http://localhost:9000/vendor.bundle.js:10600:26) at _createProviderInstance$1 (http://localhost:9000/vendor.bundle.js:10543:26) at initNgModule (http://localhost:9000/vendor.bundle.js:10494:13) at new NgModuleRef_ (http://localhost:9000/vendor.bundle.js:11602:9) at createNgModuleRef (http://localhost:9000/vendor.bundle.js:11586:12) at Object.debugCreateNgModuleRef [as createNgModuleRef] (http://localhost:9000/vendor.bundle.js:13870:12) at NgModuleFactory_.create (http://localhost:9000/vendor.bundle.js:14865:25) at http://localhost:9000/vendor.bundle.js:5552:61 at ZoneDelegate.invoke (http://localhost:9000/vendor.bundle.js:289131:26) at Object.onInvoke (http://localhost:9000/vendor.bundle.js:4929:37) at ZoneDelegate.invoke (http://localhost:9000/vendor.bundle.js:289130:32) at Zone.run (http://localhost:9000/vendor.bundle.js:288923:43) at NgZone.run (http://localhost:9000/vendor.bundle.js:4797:62) at PlatformRef_._bootstrapModuleFactoryWithZone (http://localhost:9000/vendor.bundle.js:5550:23) at http://localhost:9000/vendor.bundle.js:5592:59 at ZoneDelegate.invoke (http://localhost:9000/vendor.bundle.js:289131:26) at Zone.run (http://localhost:9000/vendor.bundle.js:288923:43) at http://localhost:9000/vendor.bundle.js:289510:57 at ZoneDelegate.invokeTask (http://localhost:9000/vendor.bundle.js:289164:31) at Zone.runTask (http://localhost:9000/vendor.bundle.js:288963:47) at drainMicroTaskQueue (http://localhost:9000/vendor.bundle.js:289343:35) at <anonymous> consoleError @ zone.js:522 handleUnhandledRejection @ zone.js:527 _loop_1 @ zone.js:562 drainMicroTaskQueue @ zone.js:566 Promise resolved (async) scheduleQueueDrain @ zone.js:505 scheduleMicroTask @ zone.js:513 ZoneDelegate.scheduleTask @ zone.js:356 Zone.scheduleTask @ zone.js:196 Zone.scheduleMicroTask @ zone.js:207 scheduleResolveOrReject @ zone.js:711 ZoneAwarePromise.then @ zone.js:800 PlatformRef_._bootstrapModuleWithZone @ core.es5.js:4596 PlatformRef_.bootstrapModule @ core.es5.js:4581 (anonymous) @ ng2app.module.ts:140 __webpack_require__ @ bootstrap 2f644bad14cb0bb324ab:691 fn @ bootstrap 2f644bad14cb0bb324ab:110 (anonymous) @ app.js:116 __webpack_require__ @ bootstrap 2f644bad14cb0bb324ab:691 fn @ bootstrap 2f644bad14cb0bb324ab:110 (anonymous) @ util (ignored):1 __webpack_require__ @ bootstrap 2f644bad14cb0bb324ab:691 webpackJsonpCallback @ bootstrap 2f644bad14cb0bb324ab:23 (anonymous) @ app.bundle.js:1 
+5
source share
3 answers

There seems to be a problem with timming permissions @NgModule({ providers: [] }) and upgrade.bootstrap .

Here you will need the $injector , but it was not entered at the time it was requested.

The docs say you should use the ngDoBootstrap hook.

 export function userServiceFactory(i: any) { return i.get('UserService'); } export const userServiceProvider = { provide: 'UserService', useFactory: userServiceFactory, deps: ['$injector'] }; import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; @NgModule({ imports: [ BrowserModule, UpgradeModule, ], declarations: [], entryComponents: [], providers: [ userServiceProvider ] }) export default class Ng2AppModule { constructor(private upgrade: UpgradeModule) { } ngDoBootstrap() { this.upgrade.bootstrap(document.body, ['app'], { strictDi: true }); } } platformBrowserDynamic().bootstrapModule(Ng2AppModule); 

edited by andrew luhring for posterity Unfortunately this did not work, although exactly what is written in the angular docs. The initial answer is here:

 import { forwardRef } from '@angular/core'; useFactory: (forwardRef(() => '$injector')i: any) => i.get('UserService') 

and it was more like an answer than this. This doesn't work either, but TypeScript doesn't seem to think the syntax is correct.

Update

We were so obsessed with useFactory that we did not see that the fix was to simply add forwardRef to the service.

 @Injectable() export class AnAngularService{ constructor(@Inject(forwardRef(() => 'UserService')) private userService: UserService ){} } 
+1
source

Ok, so I figured out the hack to get it working. it is super gross but it works. there must be a better solution, so I don’t think it can be solved, and the one who came up with the best solution still gets the award.

 import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; @NgModule({ imports: [ BrowserModule, UpgradeModule, ], declarations: [], entryComponents: [], providers: [ // angularJS service: { provide: 'UserService', useFactory: () => { return new Promise((resolve) => { setTimeout(function(){ resolve(angular.element(document) .injector().get('UserService')) },1); }) }, deps: [] }, ] }) export default class Ng2AppModule { constructor(){} } 

^ return the promise and use setTimeout to wait for the next tick before the angularJS injector resolves.

In your service:

 import {Injectable, Inject} from "@angular/core"; import UserService from 'app/login/user.service'; @Injectable() export class AnAngularService{ constructor( @Inject('UserService') private userService: any, ){ userService.then(function(_userService){ _userService.doAThing(); }); } } 

In your component:

 import { Component } from '@angular/core'; import {Inject} from "@angular/core"; import UserService from 'app/login/user.service'; import template from 'tmpl.html'; @Component({ selector: 'an-angular-component', template, }) export class AnAngularComponent{ constructor( @Inject('UserService') private userService: any, ){ userService.then((us)=>{ console.log(us); }) } } 

So yes. It works. But it's a hack. So it is possible. How can I do this in a less hacked way?

+1
source

I managed to work around this problem using the Angular Core Injector class to get the updated AngularJs service when needed, instead of injecting it into the constructor.

 import { Injector } from '@angular/core'; @Injectable() class MyAngularService { constructor(private injector: Injector) { // } myMethodUsingUpgradedService() { const myAngularJsUpgradedService = this.injector('MyAngularJsUpgradedService'); // myAngularJsUpgradedService is now available } } 
0
source

Source: https://habr.com/ru/post/1270802/


All Articles