我知道这个问题已经被问了好几次,但请记住我的具体问题,因为我找不到任何正确解决它的东西。
我有一个effect
,应该按特定顺序执行多个 HTTP 请求 - 调用 1、调用 2、调用 3。我希望能够捕获整个链中抛出的任何错误。我想保持rxjs
运算符的结构尽可能平坦,以避免嵌套的意大利面条代码。
下面是示例代码:
getMockDataEffect$ = createEffect(
() => this.actions$.pipe(
ofType(ApiGetMockData),
concatMap(() => {
return this.mockApi.mock1().pipe(
concatMap(() => {
return this.mockApi.mock2();
}),
concatMap(() => {
return this.mockApi.mock3();
}),
map(res => ApiSuccess({ data: res })),
catchError(error => of(ApiError({ error }))),
)
}
)
)
)
在上面给出的示例中,如果在mock2
或mock3
中发生错误,则会成功捕获该错误。但是,如果在mock1
中发生,则根本不会捕获错误。
我的问题是:我如何构建我的效果,使我的catchError
运算符能够捕获mock1
、mock2
或mock3
中发生的任何错误,而无需完成效果的可观察性?这意味着,如果发生错误,我应该能够调度操作并在此之后成功运行效果。
这是一个StackBlitz演示。
我认为你的例子很好。
问题是throw
,因为我认为这是针对 JavaScript 执行的,它只是停止,因为它没有被捕获。
一个现实的情况是函数以可观察格式返回错误,为此您必须使用throwError
.当 http 请求失败时,它将是一个可观察到的错误。
因此,要使您的情况正常工作,请将mockapi.service.ts
更改为以下内容:
import { Injectable } from '@angular/core';
import { of, throwError } from 'rxjs';
import { map, tap } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class MockApiService {
mock1() {
//return throwError('e1');
return of('mock1');
}
mock2() {
// return throwError('e2');
return of('mock2');
}
mock3() {
// return throwError('e3');
return of('mock3');
}
}
取消对任何throwError
的注释,以模拟它的任何函数出错。