我们有一个Angular Universal应用程序,我们需要在其中运行服务器端时将node.js中的值传递给angular。我们通过在server.ts中使用以下代码解决了这个问题:
const theValue: TheType = nodeLogicToRetrieveValue();
app.engine('html', (_, options, callback) => {
let engine = ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP),
{ provide: 'theKey', useFactory: () => theValue, deps: [] }
]
});
engine(_, <any>options, callback)
});
在组件中,我们使用以下代码解决此对象:
if (isPlatformServer(this.platformId)) {
this.theValue = this.injector.get('theKey');
}
这很好,但是掉毛会发出以下警告:
已弃用:从v4.0.0起使用Type
或InjectionToken
我们尝试将其更改为,以便我们使用InjectionToken(new InjectionToken<TheType>('theKey')
)或类型而不是字符串,但这将不起作用:
错误:StaticInjectorError(AppServerModule)[TheType]: StaticInjectorError(平台:核心)[TheType]: NullInjectorError:TheType没有提供程序!
是否只能通过字符串标记将值从节点传递到角度?
答案 0 :(得分:1)
可以通过为InjectionToken提供字符串(用作键)作为值来完成。可以将InjectionToken键入为TheType
,并且lint将不会发出警告。
在单独的文件中创建InjectionToken,以避免循环依赖。
tokens.ts
export const TOKEN = new InjectionToken<TheType>('theKey');
在appServerModule中提供InjectionToken。
app.server.module.ts
providers: [
....
{ provide: TOKEN, useValue: 'theKey', deps: [] }
]
注入令牌并用@Optional()
装饰,因为浏览器还将尝试注入令牌(并且由于缺少提供者而失败)。从node传递的值仅与服务器有关,不需要为appModule
提供InjectionToken。
app.component.ts
constructor(@Optional() @Inject(TOKEN) private token: InjectionToken<TheType>, ...){
if (isPlatformServer(this.platformId)) {
this.theValue = this.injector.get(this.token);
}
}
答案 1 :(得分:1)
我必须调整Emil的答案才能使其正常工作(我使用的是角度10)。
export const CLIENT_ID = new InjectionToken<string>('client-id');
app.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
providers: [
{
provide: CLIENT_ID,
useValue: 'MyClientId',
},
],
}) as any);
constructor(@Optional() @Inject(CLIENT_ID) private clientId: string){
console.log(this.clientId);
}