当用作Angular 4 AoT

时间:2017-04-17 05:59:40

标签: javascript angular typescript angular2-aot angular-compiler-cli

提前编译Angular 4.0.2应用程序,并将提供程序定义为useValue

import { OpaqueToken, Provider } from '@angular/core';

export const windowToken = new OpaqueToken('window');
export const windowProvider = { provide: windowToken, useValue: window };

并使用

@NgModule({ providers: [windowProvider], ... })
export class AppModule {}

它编译正常,但当注入为

时导致windowundefined
constructor(@Inject(windowToken) window) {
   window.navigator...
}

引导时抛出错误:

  

TypeError:无法读取未定义的属性“navigator”

仔细查看自动生成的app.module.ngfactory.js,看来它确实是undefined

...
import * as import39 from './window';
var AppModuleInjector = (function (_super) {
    ...
    AppModuleInjector.prototype.createInternal = function () {
        ...
        this._windowToken_26 = undefined;
        this._SomeService_27 = new import16.SomeService(this._windowToken_26);
    }
    AppModuleInjector.prototype.getInternal = function (token, notFoundResult) {
        ...
        if ((token === import39.windowToken)) {
            return this._windowToken_26;
        }
        ...

当同一服务用作useFactory时,一切正常:

export function windowFactory() {
  return window;
}
export const windowProvider = { provide: windowToken, useFactory: windowFactory };

在这里使用window useValue提供商有什么问题?这是一个众所周知的陷阱吗?此限制是否适用于所有全局或所有useValue提供程序?

2 个答案:

答案 0 :(得分:2)

我遇到了类似的问题,但是有一个SignalrWindow。这个概念和错误虽然相同。

然后我在这里找到了这篇文章(https://blog.sstorie.com/integrating-angular-2-and-signalr-part-2-of-2/),文章底部有一些评论帮我解决了这个问题。

基本上,它可以在提供程序中使用工厂方法而不是useValue。我不确定为什么这是一个问题,但我知道这种方法解决了这个问题。

要修复的步骤:

创建导出的函数

export function windowFactory(): any {
    return window;
}

然后在核心模块中,在提供程序的@NgModule中,您可以执行此操作:

...
providers: [
    { provide: SignalrWindow, useFactory: windowFactory }
  ]
...

基本上,您可以根据需要重命名方法(因此,在您的示例中,它将是:)

export const windowProvider = { provide: windowToken, useFactory: windowFactory };

答案 1 :(得分:1)

在AoT编译期间,angular CLI静态分析代码也生成ngmodule.factory文件。它看到“useValue”并检查静态值是否可用并将其放入ngmodule.factory。在编译期间,此值不可用,因此它将保留该提供程序值,因此,当将其注入constuctor时,它将返回为“undefined”。

但是,“useFactory”提供的目的非常相同,直到运行时才知道你的值。

因此,useValue在您的方案中不起作用,但“useFactory”将起作用。

底线:当AOT编译时,只有在具有常量字符串或数字的静态值时才使用“useValue”。否则使用“useFactory”返回运行时计算的对象/值。