我的Angular 5项目中有一个服务,其中包含一些配置状态:
@Injectable
export class FooService {
isIncognito: boolean = null;
constructor() {
// I want Angular to wait for this to resolve (i.e. until `isIncognito != null`):
FooService.isIncognitoWindow()
.then( isIncognito => {
this.isIncognito= isIncognito;
} );
}
private static isIncognitoWindow(): Promise<boolean> {
// /sf/ask/203655721/
// https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem
return new Promise<boolean>( ( resolve, reject ) => {
let rfs = window['requestFileSystem'] || window['webkitRequestFileSystem'];
if( !rfs ) {
console.warn( "window.RequestFileSystem not found." );
resolve( false );
}
const typeTemporary = 0;
const typePersistent = 1;
// requestFileSystem's callbacks are made asynchronously, so we need to use a promise.
rfs(
/*type: */ typeTemporary,
/* bytesRequested: */ 100,
/* successCallback: */ function( fso: WebKitFileSystem ) {
resolve( false );
},
/* errorCallback: */ function( err: any /* FileError */ ) {
resolve( true );
}
);
} );
}
}
Run Code Online (Sandbox Code Playgroud)
我的项目中的许多组件都使用了此服务,并且将该服务作为构造函数参数传递。例如:
@Component( {
moduleId: module.id,
templateUrl: 'auth.component.html'
} )
export class AuthComponent implements OnInit {
constructor( private fooService: FooService ) {
}
ngOnInit(): void {
// do stuff that depends on `this.fooService.isIncognito != null`
}
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望Angular FooService::isIncognitoWindow()在将注入FooService其他组件之前先等待诺言解决(解决方案立即发生,而不是同步发生)。
另一种解决方案是将FooComponent.isIncognito的属性更改为a Promise<boolean>,然后再次解决它,然后ngOnInit通过回调调用其余的属性,但这意味着每个组件都将导致再次调用promise的main函数-这意味着可能将其更改为缓冲的Observable或取而代之的是主题,这变得不必要地复杂-所有这些都只有一个boolean值。这也意味着重构很多我不想做的代码。
您可以使用APP_INITIALIZER令牌来确保FooService在启动应用程序之前已初始化您的令牌。在下面的代码中,angular仅在load方法返回的promise 解析后才启动应用程序。
FooService.ts
@Injectable()
export class FooService {
isIncognito: boolean = null;
public load()// <=== the method to be called and waited on during initialiation
{
return FooService.isIncognitoWindow().then(isIncognito =>
{
this.isIncognito = isIncognito;
});
}
private static isIncognitoWindow(): Promise<boolean> {
{ //your method here
Run Code Online (Sandbox Code Playgroud)
app.module.ts
export function loadFooService(fooService: FooService): Function
{
return () => { return fooService.load() };
}
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ],
providers: [ FooService,
{ provide: APP_INITIALIZER, useFactory:loadFooService , deps: [FooService], multi: true },]
})
Run Code Online (Sandbox Code Playgroud)
请参阅stackblitz示例