在我的 Angular + ngrx 应用程序中,我有一个由
@Effect
触发的 Action
。代码如下
@Effect()
customAction$ = this._actions$.pipe(
ofType<CustomAction>(Actions.CustomAction),
tap(() => console.log('Custom Action was triggered')),
switchMap((res) => {
console.log('before http request...');
this.myservice.DoApiCall().pipe(finalize(() => {
console.log('finalize triggered...');
})).subscribe(resultInner => {
console.log('next() trigerred...');
// other logic ....
},
() => {
console.log('error() triggered...');
});
return EMPTY;
})
);
我的问题是,当我有时遇到网络问题并且触发操作(然后http请求尝试执行)时,请求无法响应,但订阅的
error()
方法和finalize()
中的代码都没有执行
运算符。这可能吗?我猜想,如果请求未能完成,至少应该始终执行 finalize
部分。
正如评论部分和 @egorgrushin 中已经提到的那样,订阅
switchMap
的内部可观察量确实不是一个好的做法,所以我确实返回了 this.myservice.DoApiCall
的可观察量,如下所示:
@Effect()
customAction$ = this._actions$.pipe(
ofType<CustomAction>(Actions.CustomAction),
tap(() => console.log('Custom Action was triggered')),
switchMap((result) => {
return this.myservice.DoApiCall().pipe(
catchError((error) => {
// console.log('error caught');
}),
finalize(() => {
// console.log('finalize');
})
);
})
);
但是,该问题似乎仍然偶尔会重现(当这些网络问题发生时)。
我不知道
mergeMap
是否可以解决问题,但我宁愿不使用它,因为我确实希望如果链的外部可观察值再次被触发(这种情况发生是因为switchMap
),内部可观察值被取消
操作员)
绕过问题(不是解决方案)
我通过使用相当大的阈值(30 秒)在 http 请求内部可观察中链接
timer
运算符,成功地“绕过”了这个问题。
现在,当由于这些网络问题而重现问题时,这 30 秒将会过去,
catchError
区块将被触发。
您可能面临着我几年前遇到的同样问题。这是一个问题和答案:https://stackoverflow.com/a/45882434/2909375
Angular 的 http 客户端有时不会在出现某些网络问题或非常快的请求时调用任何 rxjs 回调。
另外,我建议您不要订阅内部效果。相反,您必须返回底层可观察值:
@Effect()
customAction$ = this._actions$.pipe(
ofType<CustomAction>(Actions.CustomAction),
tap(() => console.log('Custom Action was triggered')),
switchMap(() => this.myservice.DoApiCall().pipe(
catchError(() => {
console.log('error() triggered...');
return EMPTY;
}),
finalize(() => {
console.log('finalize triggered...');
}),
)),
);
我放置了不必要的嵌套管道,但会帮助您避免在 this._actions$ 可观察到的完成/错误处进行日志记录。
如果您希望发出下一个操作后您的请求不会被取消,您应该将
switchMap
替换为 mergeMap
。