Angular "APP_INITIALIZER" 没有承诺在 angular 4 中提供服务?
Angular "APP_INITIALIZER" to have service without promise in angular 4?
我有一个应用程序存在于父应用程序的 iframe 中。
当我在 iFrame 中的应用程序加载时,在我的应用程序 AppModule 中,我有一个名为 tokenService 的 APP_INITIALIZER。此服务向父应用程序发送 window.sendMessage 以获取令牌。所以令牌服务中有一个"message"事件处理程序。
代码如下:
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" 作为 promise 方法。任何人都可以帮我吗?
因为当我尝试 运行 应用程序时出现错误。错误是:
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
已经 returns 可观察。 APP_INITIALIZER
需要异步初始化的承诺,因此应将可观察对象转换为承诺:
'deps': [tokenService],
'multi': true,
},
和
export function loadService(tService: tokenService): Function {
return () => tService.getToken().toPromise();
}
ConfigurationService
的问题在于它是异步的,但它只公开了 getConfigurationData
在某个时候可用的承诺的结果。多次调用 getConfiguration
将导致重复请求。它应该公开一个可以轻松链接的承诺或可观察对象:
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);
}
}
我有一个应用程序存在于父应用程序的 iframe 中。
当我在 iFrame 中的应用程序加载时,在我的应用程序 AppModule 中,我有一个名为 tokenService 的 APP_INITIALIZER。此服务向父应用程序发送 window.sendMessage 以获取令牌。所以令牌服务中有一个"message"事件处理程序。
代码如下:
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" 作为 promise 方法。任何人都可以帮我吗? 因为当我尝试 运行 应用程序时出现错误。错误是:
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
已经 returns 可观察。 APP_INITIALIZER
需要异步初始化的承诺,因此应将可观察对象转换为承诺:
'deps': [tokenService],
'multi': true,
},
和
export function loadService(tService: tokenService): Function {
return () => tService.getToken().toPromise();
}
ConfigurationService
的问题在于它是异步的,但它只公开了 getConfigurationData
在某个时候可用的承诺的结果。多次调用 getConfiguration
将导致重复请求。它应该公开一个可以轻松链接的承诺或可观察对象:
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);
}
}