I am currently working on an app embedded within an iframe of a parent application.
Upon loading my app within the iframe, I have configured an APP_INITIALIZER in my AppModule called tokenService. This service is responsible for sending a message to the parent application in order to retrieve a token. As a result, there is a "message" event handler included in the token service code.
Here is the snippet of the code:
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);
};
}
The method "processMessage" will be triggered upon receiving the response.
Moreover, the "tokenService" has been set as an "APP_INITIALIZER". Here's how it's done:
{
'provide': APP_INITIALIZER,
'useFactory': loadService,
'deps': [ConfigurationService, tokenService],
'multi': true,
},
The initialization of the configService is also essential:
export function loadConfig(config: ConfigurationService): Function {
return () => config.configuration$;
}
{
'provide': APP_INITIALIZER,
'useFactory': loadConfig,
'deps': [ConfigurationService],
'multi': true,
}
In the app.module.ts file, there is a specific method:
export function loadService(tService: tokenService): Function {
return () => tService.getToken();
}
I am currently facing an issue with converting the event handler "processMessage" into a promise method. Can someone provide guidance on this matter? I encounter an error when attempting to run the application which states:
ERROR TypeError: tService.getToken is not a function
at Array.eval (app.module.ts:44)
at ApplicationInitStatus.runInitializers (core.js:3569)
Additionally, I would like to ensure that the tokenService completes its execution before any other components within my application are initialized. How can I guarantee that the tokenService finishes execution and the event handler for sendMessage is invoked prior to proceeding with the loading of other components?
Below is the code for the configuration service:
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;
}
}
Your assistance is greatly appreciated.
Thank you in advance.