[英]Angular - APP_INITIALIZER - Promise vs Observable
[英]Angular "APP_INITIALIZER" to have service without promise in angular 4?
我有一个应用程序,它存在于父应用程序的 iframe 中。
当 iFrame 中的应用程序加载时,在我的应用程序 AppModule 中,我有一个名为 tokenService 的 APP_INITIALIZER。 此服务向父应用程序发送 window.sendMessage 以获取令牌。 所以令牌服务中有一个“消息”事件处理程序。
下面是代码:
import { Injectable } from '@angular/core';
import { ConfigurationService } from './configService';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class tokenService {
private _configs;
private msgId = this.newId();
private messageToGetToken = {
'id': this.msgId,
'type': 'test/V/GetToken',
'data': null
};
constructor(private configService: ConfigurationService) {
this._configs = configService.getConfigurationData();
}
getToken() {
if (this._configs.loginRequired == true) {
if (window.addEventListener) {
window.addEventListener('message', this.processMessage, false);
}
else {
(<any>window).attachEvent("onmessage", this.processMessage);
}
parent.window.postMessage(JSON.stringify(this.messageToGetToken), '*');
return Observable.fromEvent(window, 'message')
.subscribe((messageEvent: MessageEvent) => { this.processMessage(messageEvent); });
}
}
private processMessage(evt) {
var result = JSON.parse(evt);
if (result && result.responseFor && result.responseFor === this.msgId) {
localStorage.setItem('token', result.data ? result.data[0] : null);
console.log(result.data);
}
console.log(evt);
}
private newId() {
return '_' + Math.random().toString(36).substr(2, 9);
};
}
当结果返回时,将调用方法“processMessage”。
“tokenService”已设置为“APP_INITIALIZER”。 下面是代码:
{
'provide': APP_INITIALIZER,
'useFactory': loadService,
'deps': [ConfigurationService, tokenService],
'multi': true,
},
configService 也被初始化:
export function loadConfig(config: ConfigurationService): Function {
return () => config.configuration$;
}
{
'provide': APP_INITIALIZER,
'useFactory': loadConfig,
'deps': [ConfigurationService],
'multi': true,
}
在 app.module.ts 文件中,有方法:
export function loadService(tService: tokenService): Function {
return () => tService.getToken();
}
我不确定如何使这个事件处理程序:“processMessage”作为承诺方法。 任何人都可以帮助我吗? 因为当我尝试运行应用程序时出现错误。 错误是:
ERROR TypeError: tService.getToken is not a function
at Array.eval (app.module.ts:44)
at ApplicationInitStatus.runInitializers (core.js:3569)
另外,我想让这个 tokenService 在我的应用程序中的其他组件被初始化之前完成它的执行。 在应用程序继续加载其他组件之前,如何确保 tokenService 已完成执行并调用了 sendMessage 的事件处理程序?
配置服务的代码如下:
import { Http } from '@angular/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/catch';
@Injectable()
export class ConfigurationService {
private configuration;
constructor(private http: Http) {
}
getConfiguration(): Promise<any> {
let ret = this.http.get('appConfig.json').map(
res => this.configuration = res.json())
.toPromise()
.then((data: any) => {
this.configuration = data;
})
.catch((err: any) => {
console.log("error while reading app config!");
});
return ret.then((x) => {
});
}
getConfigurationData(): any {
return this.configuration;
}
}
任何帮助表示赞赏。
提前致谢。
tService.getToken
未定义,因为 DI 出错了,而tService
实际上是ConfigurationService
。 [ConfigurationService, tokenService]
注解表示会注入2个依赖,而工厂函数只有1个参数。
如果它不使用ConfigurationService
,则不必注入它。
getToken
已经返回一个 observable。 APP_INITIALIZER
期望异步初始化的承诺,因此应将 observable 转换为承诺:
'deps': [tokenService],
'multi': true,
},
和
export function loadService(tService: tokenService): Function {
return () => tService.getToken().toPromise();
}
ConfigurationService
的问题在于它是异步的,但它只公开了在某些时候可通过getConfigurationData
使用的承诺的结果。 多次调用getConfiguration
将导致重复请求。 它应该公开一个可以轻松链接的 promise 或 observable:
export class ConfigurationService {
public configurationPromise = this.getConfiguration().toPromise();
public configuration;
constructor(private http: Http) {
this.configurationPromise.then(configuration => {
this.configuration = configuration;
});
}
private getConfiguration(): Observable<any> {
return this.http.get('appConfig.json').map(res => res.json())
}
}
然后configurationPromise
可以链接到任何地方,它不仅限于 promise 控制流:
export class tokenService {
...
constructor(private configService: ConfigurationService) {}
getToken(): Observable<any> {
...
return Observable.fromPromise(configService.configurationPromise)
.switchMap(() => Observable.fromEvent(window, 'message'))
.map((messageEvent: MessageEvent) => this.processMessage(messageEvent))
.take(1);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.