Angular NgUpgrade 将 AngularJS 服务注入 Angular 服务;获取:未处理的承诺拒绝:无法读取未定义的 属性 'get' ;区:
Angular NgUpgrade inject AngularJS service into Angular service; getting: Unhandled Promise rejection: Cannot read property 'get' of undefined ; Zone:
我在这里看到很多类似的问题,但尚未找到有效的解决方案。我认为正在发生的事情是,因为我们的 Ng2App 首先被引导,它还没有对 $injector 的引用,所以当我尝试在我的提供者声明(deps:['$injector'])中使用它时,它没有'不存在。
非常奇怪的是,我可以在 Angular 组件中使用此服务,但由于某种原因不能在 Angular 服务中使用它。
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});
});
稍后...在服务中(失败):
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
){}
}
稍后...在组件中(正常工作):
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 <--------------
}
}
有谁知道为什么会发生这种情况以及如何解决它?
This question is almost exactly the same thing but for some reason it didnt work
AngularJS版本:1.5.8
Angular/core等版本:4.2.4
Here's a link to the Github issue I opened in the Angular repo
堆栈跟踪:
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 (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 (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
好的,所以我想出了一个让它工作的技巧。这太恶心了,但它确实有效。必须有更好的解决方案,所以我不会将此标记为已解决,无论谁提出更好的解决方案,仍然会得到赏金。
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 承诺并在解决 angularJS 注入器之前使用 setTimeout 等待下一次滴答。
为您服务:
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();
});
}
}
在你的组件中:
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); })
}
}
是的。这行得通。但这是一个黑客。所以这是可能的。我怎样才能以一种不那么骇人听闻的方式做到这一点?
这似乎是 @NgModule({ providers: [] })
和 upgrade.bootstrap
决议的时机问题。
此处您需要 $injector
,但在请求时并未注入。
在 docs 中它说你应该使用 ngDoBootstrap
钩子。
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);
由 andrew luhring 为后代编辑
不幸的是,即使那正是 angular 文档中所写的内容,它也不起作用。这里原来的答案是:
import { forwardRef } from '@angular/core';
useFactory: (forwardRef(() => '$injector')i: any) => i.get('UserService')
这似乎比这个更接近答案。这也不起作用——但这似乎是因为 TypeScript 认为语法不正确。
更新:
我们对 useFactory
如此着迷,以至于我们没有看到修复只是将 forwardRef
添加到服务中。
@Injectable()
export class AnAngularService{
constructor(@Inject(forwardRef(() => 'UserService')) private userService: UserService
){}
}
我能够通过使用 Angular Core Injector
class 在需要时获取升级的 AngularJs 服务来解决这个问题,而不是注入它在构造函数中。
import { Injector } from '@angular/core';
@Injectable()
class MyAngularService {
constructor(private injector: Injector) {
//
}
myMethodUsingUpgradedService() {
const myAngularJsUpgradedService = this.injector('MyAngularJsUpgradedService');
// myAngularJsUpgradedService is now available
}
}
我在这里看到很多类似的问题,但尚未找到有效的解决方案。我认为正在发生的事情是,因为我们的 Ng2App 首先被引导,它还没有对 $injector 的引用,所以当我尝试在我的提供者声明(deps:['$injector'])中使用它时,它没有'不存在。
非常奇怪的是,我可以在 Angular 组件中使用此服务,但由于某种原因不能在 Angular 服务中使用它。
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});
});
稍后...在服务中(失败):
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
){}
}
稍后...在组件中(正常工作):
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 <--------------
}
}
有谁知道为什么会发生这种情况以及如何解决它?
This question is almost exactly the same thing but for some reason it didnt work
AngularJS版本:1.5.8
Angular/core等版本:4.2.4
Here's a link to the Github issue I opened in the Angular repo
堆栈跟踪:
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 (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 (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
好的,所以我想出了一个让它工作的技巧。这太恶心了,但它确实有效。必须有更好的解决方案,所以我不会将此标记为已解决,无论谁提出更好的解决方案,仍然会得到赏金。
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 承诺并在解决 angularJS 注入器之前使用 setTimeout 等待下一次滴答。
为您服务:
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();
});
}
}
在你的组件中:
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); })
}
}
是的。这行得通。但这是一个黑客。所以这是可能的。我怎样才能以一种不那么骇人听闻的方式做到这一点?
这似乎是 @NgModule({ providers: [] })
和 upgrade.bootstrap
决议的时机问题。
此处您需要 $injector
,但在请求时并未注入。
在 docs 中它说你应该使用 ngDoBootstrap
钩子。
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);
由 andrew luhring 为后代编辑 不幸的是,即使那正是 angular 文档中所写的内容,它也不起作用。这里原来的答案是:
import { forwardRef } from '@angular/core';
useFactory: (forwardRef(() => '$injector')i: any) => i.get('UserService')
这似乎比这个更接近答案。这也不起作用——但这似乎是因为 TypeScript 认为语法不正确。
更新:
我们对 useFactory
如此着迷,以至于我们没有看到修复只是将 forwardRef
添加到服务中。
@Injectable()
export class AnAngularService{
constructor(@Inject(forwardRef(() => 'UserService')) private userService: UserService
){}
}
我能够通过使用 Angular Core Injector
class 在需要时获取升级的 AngularJs 服务来解决这个问题,而不是注入它在构造函数中。
import { Injector } from '@angular/core';
@Injectable()
class MyAngularService {
constructor(private injector: Injector) {
//
}
myMethodUsingUpgradedService() {
const myAngularJsUpgradedService = this.injector('MyAngularJsUpgradedService');
// myAngularJsUpgradedService is now available
}
}