Angular 在RxJs中执行操作后,如何重试可观察到的?

Angular 在RxJs中执行操作后,如何重试可观察到的?,angular,rxjs,reactive-programming,Angular,Rxjs,Reactive Programming,我使用Angular 2和RxJS从API层检索数据。我编写了一个基本服务来处理HTTP请求。以下代码在我的服务中执行此操作: protected apiGet(uri: string): Observable<HttpMappedResponse<T>> { return this.mapAndHandle<T>(this.http.get(uri)); } private mapAndHandle<T>(observable: Obs

我使用Angular 2和RxJS从API层检索数据。我编写了一个基本服务来处理HTTP请求。以下代码在我的服务中执行此操作:

protected apiGet(uri: string): Observable<HttpMappedResponse<T>> {
    return this.mapAndHandle<T>(this.http.get(uri));
}

private mapAndHandle<T>(observable: Observable<Response>): Observable<HttpMappedResponse<T>> {
    const o = observable
        .map(res => {
            const data = res.json() || {};
            const mappedResponse = new HttpMappedResponse<T>(res, data);
            // Retrieve page information from HTTP headers
            mappedResponse.pageInfo = new PageInfo(res.headers);
            return mappedResponse;
        })
        .share();

    o.subscribe(null, e => this.errorService.handleHttpResponse(e));
    return o;
}
但这并没有给我正确的结果


有接线员可以帮我吗?retryWhen()似乎是最符合逻辑的,但我总是把自己和RxJs搞得一团糟

您遇到的问题之一是您没有将电话链接起来。您的刷新调用应该链接到您的重试调用,它们应该利用
flatMap
或类似的工具将其保持在相同的可观察流中


看看这个问题

以下是您实现此目标的方法:

您需要从RxJS添加
catch
操作符。这就是错误所在,您可以相应地处理它

为了让刷新逻辑通过拦截器,您需要返回调用,函数还应该返回一个可观察的
。例如,修改上述原始逻辑:

this.http.request(url, options)
        .map((res: Response) => res.json())
        .catch((error: any) => {
            const err = error.json();

            // Refresh JWT
            if (err.status === 401) {
                // refreshToken makes another HTTP call and returns an Observable.
                return this.refreshToken(...);
            }

            return Observable.throw(err);
        });
如果您希望能够重试原始请求,您可以做的是传递原始请求数据,以便在成功刷新令牌后可以再次进行调用。例如,这就是
refreshtToken
函数的外观:

refreshToken(url: string, options: RequestOptionsArgs, body: any, tokenData: any): Observable<any>
    return this.post(`${this.url}/token/refresh`, tokenData)
        .flatMap((res: any) => {
            // May want to use response data to set new tokens in your local storage or whatever here...

            // This is where I retry the original request
            return this.request(url, options, body);
        });
}
refreshttoken(url:string,options:RequestOptionsArgs,body:any,tokenData:any):可观察
返回this.post(`${this.url}/token/refresh`,tokenData)
.flatMap((res:any)=>{
//可能需要使用响应数据在本地存储或其他任何地方设置新令牌。。。
//这是我重试原始请求的地方
返回此.request(url、选项、正文);
});
}

让我知道我的答案是否能引导您走向正确的方向。这都是伪代码,但它应该让您大致了解您可以做什么(您已经知道需要采取的步骤)。在重试您的请求时,只需利用
flatMap
,您就可以将其保存在相同的可观察流中。谢谢!我看到过flatMap()的示例,但无法真正理解它以前在做什么。我还花了几个小时追踪了一个愚蠢的重构错误,我把它引入了我的代码中,它替换了我文章中的主体,并将命令放在了标题中。这当然没有帮助我理解这里!很高兴我能帮上忙:)我也被困在这个问题上了一段时间,但最终发现我可以利用
flatMap
来解决它。你可能可以让它更简洁,但你现在明白了。我的完整实现相当复杂——尝试使事情尽可能通用的本质:)this.request(url、选项、正文);这给了我最后一条线索,我有一个用于Get/Post/Put的常见错误处理程序。
refreshToken(url: string, options: RequestOptionsArgs, body: any, tokenData: any): Observable<any>
    return this.post(`${this.url}/token/refresh`, tokenData)
        .flatMap((res: any) => {
            // May want to use response data to set new tokens in your local storage or whatever here...

            // This is where I retry the original request
            return this.request(url, options, body);
        });
}