http请求的订阅next()、error()或complete()方法在请求超时时未触发

问题描述 投票:0回答:1

在我的 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
区块将被触发。

angular rxjs ngrx ngrx-effects
1个回答
0
投票

您可能面临着我几年前遇到的同样问题。这是一个问题和答案: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

© www.soinside.com 2019 - 2024. All rights reserved.