停止应用程序的初始化,直到调用 ngrx 的操作

Stop initialization of app until ngrx's action has been called

我尝试同步应用程序的初始化和 ngrx 存储的初始化。这很重要,因为应用程序使用刷新令牌机制来自动登录。种族会产生很多问题,例如 cannot read property of undefined.

APP_INITIALIZER 令牌中使用了以下方法。

// import { ActionsSubject, ScannedActionsSubject } from '@ngrx/store';
    
public async load(): Promise<any> {

    return this.refreshToken().pipe(
      tap(res => {
        this.subject.next(authActions.refreshTokenOnInitSuccess({token: res.token}));
      }),
      catchError((error: HttpErrorResponse) => {
      // SOME CODE
      }),
     takeUntil(this.actions$.pipe(ofType(authActions.initSuccess))) //  HERE, init not stop, work like without this line
    ).toPromise().catch(error => {
      console.error('Error when refreshing JWT access token on startup', error);
    });
  }

  private refreshToken(): Observable<JwtTokenResponse> {
    return this.httpClient.post<JwtTokenResponse>(`${AUTH_URL}/refresh`, {});
  }

我尝试使用 exhaustMap 而不是 takeUntil 但初始化从未结束。我知道它可以通过 Promiseresolve 修复,例如:

 return new Promise((resolve, reject) => {
      this.refreshToken().pipe(
        tap(res => {
          this.subject.next(authActions.refreshTokenOnInitSuccess({ token: res.token }));
        }),
        catchError((error: HttpErrorResponse) => {
          // SOME CODE
          reject(error);
          return throwError(error);
        }),
      ).subscribe();
      this.actions$.pipe(ofType(authActions.initSuccess)).subscribe(resolve);
    }).catch(error => {
      console.error('Error when refreshing JWT access token on startup', error);
    }); 

但我试图找到 rxjs 暂停应用程序初始化直到存储设置状态的方法。

当我 运行 陷入这样的事情时,我将我的 observables/subscription 包裹在一个 Promise 中:

const result = await new Promise<string>(resolve => {
    this.service.subscribe(res => {
        resolve(res);
    });
});

如果实施正确,应该适用于您的情况。

在触发此操作之前,您必须订阅 init 成功操作。您可以使用 forkJoin 将您的操作与 refresh/trigger 流结合起来。 (combineLatestzip 也应该有效)

public async load(): Promise<any> {
  const refresh = this.refreshToken().pipe(
    tap(res => {
      this.subject.next(authActions.refreshTokenOnInitSuccess({token: res.token}));
    }),
    catchError((error: HttpErrorResponse) => {
      // SOME CODE
    }),
  );
  return forkJoin(
    // add your action stream first, use take(1) to complete the stream
    this.actions$.pipe(ofType(authActions.initSuccess), take(1)), 
    refresh    
  ).toPromise().catch(error => {
    console.error('Error when refreshing JWT access token on startup', error);
  });
}