如何在http错误的情况下保证可观察流的连续性?
How to guarantee the continuity of observable stream in case of http errors?
当我遇到 HTTP
错误响应时,以下方法 (onTrySignin
) 出现问题。在我的 HTTP
调用之后的 catch
块阻止 Side Effect
抛出 Action
错误。如果我这样做 console.log
我会得到这个错误。
TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
如何保留 Observable
流并将响应传递到下一个块 (mergeMap
),我可以在其中触发其他 Actions
、(FailedSignin()
)这种情况?
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);
});
这是我的httpService
public postRequest(apiUrl: string, jsonData: {} = {}): Observable<any> {
return this.httpService.post(this.baseUrl + apiUrl, JSON.stringify(jsonData),
{observe: 'response', reportProgress: true, withCredentials: true});
}
您需要创建一个一次性流,我们是这样做的:
@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));
});
});
当我遇到 HTTP
错误响应时,以下方法 (onTrySignin
) 出现问题。在我的 HTTP
调用之后的 catch
块阻止 Side Effect
抛出 Action
错误。如果我这样做 console.log
我会得到这个错误。
TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
如何保留 Observable
流并将响应传递到下一个块 (mergeMap
),我可以在其中触发其他 Actions
、(FailedSignin()
)这种情况?
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);
});
这是我的httpService
public postRequest(apiUrl: string, jsonData: {} = {}): Observable<any> {
return this.httpService.post(this.baseUrl + apiUrl, JSON.stringify(jsonData),
{observe: 'response', reportProgress: true, withCredentials: true});
}
您需要创建一个一次性流,我们是这样做的:
@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));
});
});