How to guarantee the continuity of observable stream in case of http errors?

北战南征 提交于 2019-12-11 09:50:19

问题


I have a problem with the below method (onTrySignin) when I encounter an HTTP error response. The catch block right after my HTTP call prevents the Side Effect from throwing an Action error. if I do console.log I get this error.

TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

how can I preserve the Observable stream and pass the response to the next block (mergeMap) where I can fire other Actions, (FailedSignin()) in this case?

onTrySignin = this.actions$
    .ofType(AuthActions.TRY_SIGNIN)
    .map((action: AuthActions.TrySignin) => {
       return action.payload;
      })
    .switchMap((action: DispatchAction) => {
      const trySignInPayload: TrySignInPayload = action.payload;
      return this.httpService.postRequest('Account/Login', (trySignInPayload.loginData))
        .catch((error: any) => {
          console.log(error)
          return Observable.empty();
        })
        .mergeMap((response: HttpResponse<any>) => {
          switch (response.status) {
            case 200:
              if (trySignInPayload.returnUrl) {
                this.router.navigate([trySignInPayload.returnUrl]);
              } else {
                this.router.navigate(['/dbapp']);
              }
              return Observable.concat(
                Observable.of(new AuthActions.GenerateAntiforgeryToken()),
                Observable.of(new AuthActions.Signin(fromAuth.authId, this.fetchUserData()))
              );
              case 401:
              case 404:
              return Observable.concat(
                Observable.of(new AuthActions.FailedSignin()),
                Observable.empty()
              );
            default:
            return Observable.concat(
              Observable.of(new AuthActions.FailedSignin()),
              Observable.empty()
            );
          }
        })
    }).catch((error) => {
      return Observable.throw(error);
    });

This is my httpService

public postRequest(apiUrl: string, jsonData: {} = {}): Observable<any> {
        return this.httpService.post(this.baseUrl + apiUrl, JSON.stringify(jsonData),
        {observe: 'response', reportProgress: true, withCredentials: true});
    }

回答1:


You need to create a disposable stream, this is how we do it:

@Effect()
  login$: Observable<Action> = this.actions$
   .ofType(authActions.LOGIN)
   .switchMap((action: any) => {
     // @Effect stream is completing when the error occurs, preventing any further 
     // actions. Therefore create a disposable stream to keep @Effect stream alive
     return Observable.of(action)
       .switchMap((action: any) => {
         return this.apiService.login(action.payload);
       })
       .map((x: any) => {
         return new authActions.SetTokensAction({ token: x.data.token });
       })
       .catch((error: any) => {
         return Observable.of(new authActions.LoginFailedAction(error));
       });
    });


来源:https://stackoverflow.com/questions/48576629/how-to-guarantee-the-continuity-of-observable-stream-in-case-of-http-errors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!