Angular + RxJS:在状态代码202上重复请求

时间:2017-08-07 09:44:18

标签: angular rxjs

我有一个简单的请求,如果状态为 202 ,我想重复一下。目前,它看起来像这样:

this.http.get(endPoint, {
    withCredentials: true,
    headers: this.headers
})
.map((response: Response) => {
    return response.text() ? response.json() : '';
})
.catch((error) => this.handleError(error));

我尝试使用.repeatWhen(),但不幸的是,我没有收到Response对象,我无法通过状态代码设置验证。

任何想法我该怎么做?

4 个答案:

答案 0 :(得分:2)

这是对repeatWhen()如何运作的误解。对此运算符的回调接收单个参数,该参数是一个Observable,它在源完成时推送空项。所以它对你来说并不理想(因为你无法访问所需的Response对象)。

您可以改为使用retryWhen()

this.http.get(endPoint, { withCredentials: true, headers: this.headers })
    .map((response: Response) => {
        if (response.code === 202) {
            throw response;
        }
        return response;
    })
    .map((response: Response) => {
        return response.text() ? response.json() : '';
    })
    .retryWhen(obs => {
        return obs; // always just resubscribe without any further logic
    });

这会将response作为错误抛出,然后由retryWhen捕获,只会重新订阅。如果您重新订阅,您当然可以使用更多逻辑来控制,例如:

.retryWhen(obs => {
   return obs.filter(...);
});

答案 1 :(得分:0)

您可以在捕获方法

中再次进行http调用
.catch(res => {
    return res.status === 202?
        this.http.get(endPoint):
        Observable.throw(res);
});

答案 2 :(得分:0)

如何使用flatMap:

.flatMap((response:Response) => {
    if (response.status === 200) {
        return Observable.of(this.mapResponse(response.json()));
    } else if (response.status === 202) {
        return this.http.get(endPoint, {
            withCredentials: true,
            headers: this.headers
        });
    }
})

答案 3 :(得分:0)

将其用于Rx6。这将重试202次最多3次,并在第三次尝试结束时引发超时错误。

@Injectable()
export class ProgressInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        return next.handle(req).pipe(
            map(t => {
                if (t['status'] === 202) {
                    throw 202;
                }
                return t;
            }),
            retryWhen(t => {
                return t.pipe(
                    concatMap((e, i) => {
                        if (e !== 202) {
                            return throwError(e);
                        }
                        return iif(
                            () => i >= 2,
                            throwError(new Error('Operation Timed Out!')),
                            of(e).pipe(delay(1000))
                        )
                    })
                )
            }),
        );    
    }
}