在构造依赖项-或ngOnInit之前,如何使Angular 5等待Injectable的构造函数中使用的Promise解析?

Dai*_*Dai 3 promise angular

我的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值。这也意味着重构很多我不想做的代码。

Dav*_*vid 5

您可以使用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示例