可观察的重试/重试当使用flatmap时

dev*_*per 5 javascript observable rxjs angular

我有以下代码来获取id,然后获取与id相关的数据.

process(): Observable<any> {
    let id: number;
    return this.getId().flatMap(
        (response: number) => {
                id = response;
                return this.getData(id)
        }
    ).flatMap(
        (data: any) => {
            return Observable.of(data);
        }
    );
}

getData(id: number): Observable<any> {
    // retry if response.status is not complete
    return this.service.getData(id).map(response => return response.data); 
}
Run Code Online (Sandbox Code Playgroud)

我想在getData方法上添加重试逻辑,直到response.status没有完成.我尝试在this.getData(id)之后添加重试/重试但没有运气.有什么建议吗?

Ser*_*aev 4

retryretryWhen适合错误处理,这意味着源可观察量必须产生错误才能使这些运算符产生效果。我想在你的情况下,你不想重试错误,而是重试你不喜欢的状态。

实现这一目标的最简单方法可能是按一定时间间隔进行服务调用,并根据您想要的状态获取第一个响应:

getData(id) {
    return Observable.interval(100)
        // make 5 attempts to get the data
        .take(5)
        .concatMap(() => this.service.getData(id))
        .filter(response => response.status === "complete")
        .take(1)
        .map(response => response.data)
}
Run Code Online (Sandbox Code Playgroud)

现在getData()返回一个可观察对象,它要么发出与具有“完成”状态的响应相对应的单个值,然后完成,要么在 5 次尝试获取具有所需状态的数据失败后完成而不发出任何值(答案已更新以响应一条评论)

更新:

当然,可以将具有“不良”状态的响应转变为错误并使用该retry功能,如您所建议的:

getData(id) {
    return this.service.getData(id)
        .concatMap(response => response.status === "complete" ?
            Observable.of(response) :
            Observable.throw("Bad status"))
        .map(response => response.data)
        .retry(5);
}
Run Code Online (Sandbox Code Playgroud)

如果出现问题,此代码将尝试最多 6 次获取数据(1 次初始 + 5 次重试),然后将产生一个您必须处理的错误,例如使用catch运算符。一个缺点是这种方法无法区分“真实”错误(例如网络故障)和不良状态产生的错误,但这可以用retryWhen.