如何让Angular 5等待在Injectable构造函数中使用的Promise在构造dependent之前解析 - 或者ngOnInit?

时间:2018-05-11 19:37:47

标签: angular promise

我的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> {
    // https://stackoverflow.com/questions/2909367/can-you-determine-if-chrome-is-in-incognito-mode-via-a-script
    // 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 );
                }
            );
        } );
    }
}

我的项目中的许多组件都使用此服务,并将其作为构造函数参数传递。例如:

@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`
    }
}

理想情况下,我希望Angular在将FooService::isIncognitoWindow()注入其他组件之前先等待FooService承诺解决(解决方案立即发生,但不是同步)。

另一种解决方案是将FooComponent.isIncognito的属性更改为Promise<boolean>并再次解析它并通过回调调用ngOnInit的其余部分,但这意味着每个组件都将导致promise的主要功能再次被调用 - 这意味着可能会将其更改为缓冲的Observable或Subject,而且会变得不必要地复杂化 - 所有这些都是针对单个boolean值的。这也意味着重构很多代码,而不是必须这样做。

2 个答案:

答案 0 :(得分:3)

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

<强> 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 },]
})

请参阅stackblitz example

答案 1 :(得分:0)

如果return view("demmande.demmandes") ->with('villes', $villes) ->with('categorie', $categorie) ->with('demande', $demande); 返回isIncognitoWindow,请尝试以下操作:

Promise