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

时间:2017-07-28 11:05:34

标签: javascript angular rxjs observable

我有以下代码来获取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); 
}

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

2 个答案:

答案 0 :(得分:4)

retryretryWhen适用于错误处理,这意味着源observable必须为这些运算符产生错误才能生效。我想在你的情况下,你想重试不是出错,而是在你不喜欢的状态。

实现这一目标的最简单方法可能是在某个时间间隔内进行服务调用,并采用您想要的状态进行第一次响应:

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)
}

现在getData()返回一个observable,该observable发出一个对应于具有“完成”状态的响应的值,然后完成,或完成,但在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);
}

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

答案 1 :(得分:0)

我尝试过重试方法,但它确实有效。

(Observable ...).retry(2).map(...).subscribe(...)

当我进行http呼叫并且响应是例如404时,它重试该呼叫两次。