Angular 单击按钮时重试http请求

Angular 单击按钮时重试http请求,angular,typescript,rxjs,angular-httpclient,Angular,Typescript,Rxjs,Angular Httpclient,假设我们有一个组件,其方法执行服务中定义的http请求。我们订阅组件中某个地方的可观察内容(也可以在模板中): 组件: getData() { this.apiService.getDataFromServer().subscribe( a => console.log(a), b => console.error(b) ); } getDataFromServer() { return this.http.get(); }

假设我们有一个组件,其方法执行服务中定义的http请求。我们订阅组件中某个地方的可观察内容(也可以在模板中):

组件:

getData() {
    this.apiService.getDataFromServer().subscribe(
        a => console.log(a),
        b => console.error(b)
    );
}
getDataFromServer() {
    return this.http.get();
}
API服务:

getData() {
    this.apiService.getDataFromServer().subscribe(
        a => console.log(a),
        b => console.error(b)
    );
}
getDataFromServer() {
    return this.http.get();
}
当请求失败时,我想打开一个向用户显示错误的模式。在这个模式下,用户会发现两个按钮:一个是“重新加载”,另一个是“取消”。如果单击其中一个按钮,模式将再次关闭

现在,一种(廉价的)处理方法是从组件中的错误案例再次调用
getData()
。当然,在服务级别处理错误会更好。这就是我在这里努力实现的目标


我现在正试图找出如何处理按钮点击。使用
管道
捕捉错误
,无法“等待”服务方法中的重新加载按钮点击。我认为处理这个问题的一个好方法是
retryWhen
,但我不知道怎么做

下面是我扩展API服务的尝试:

// The modal with the two buttons will call 
// - this.apiService.button$.next(true) if the user wants to reload, or 
// - this.apiService.button$.next(false) if the user does not want to reload
button$ = new Subject<boolean>();

getDataFromServer() {
    return this.http.get().pipe(
        retryWhen((errors: Observable<any>) => {

            this.openErrorModal(); // this is a simple method that shows the modal to the user

            // how to use the button$ subject here?
            // I tried with 
            // - return this.button$.pipe(), and 
            // - return errors.pipe(), 
            // but I was not able to finalize it to make it work

        }
    );
}

openErrorModal() {
    // Open a modal with a simple GUI
}
//带有两个按钮的模式将调用
//-此.apiService.button$.next(true),如果用户希望重新加载,或
//-如果用户不想重新加载,则此.apiService.button$.next(false)
按钮$=新主题();
getDataFromServer(){
返回此.http.get().pipe(
retryWhen((错误:可观察)=>{
this.openErrorMode();//这是一个向用户显示模式的简单方法
//如何在此处使用$subject按钮?
//我试过了
//-返回此.button$.pipe(),然后
//-返回错误。管道(),
//但我没能最终完成它,让它发挥作用
}
);
}
openErrorModal(){
//使用简单的GUI打开模式
}

最后,我的目标是,组件在不知道请求执行频率的情况下获取数据或错误。基本上,每次请求失败时都会打开错误模式,因此用户可以根据自己的意愿将自己保持在无限循环中。只要单击“取消”,就不会再执行请求


<> >注意:我的问题被大大简化了。我试图删除所有与问题无关的代码。

你可以稍微改变一下你的设计以获得你想要的行为。在中间添加一个主题(而不是从代码中返回可观察到的GETDATA.Server < /Case>函数)。

通过这种方式,您可以在出现故障时重试服务,如果您将其实现为服务的基本函数,则可以使用它包装每个调用并避免代码重复

它看起来像:

tempSubject: Subject<any>;
getDataFromServer() {
  this.tempSubject = new Subject();    
  this.getDataFromServerInternal(this.tempSubject);
  return this.tempSubject;
}

private getDataFromServerInternal(sub: Subject < any > ) {
  this.httpClient
    .get()
    .subscribe(
      (res) => sub.next(res),
      (error) => {
        const confirmed = confirm(`try again? error: ${error}`);
        if (confirmed) {
          this.getDataFromServerInternal(sub);
        }
      }
    );
}
tempSubject:Subject;
getDataFromServer(){
this.tempSubject=新主题();
this.getDataFromServerInternal(this.tempSubject);
返回此.temp主题;
}
私有getDataFromServerInternal(子:主题){
这个是.httpClient
.get()
.订阅(
(res)=>sub.next(res),
(错误)=>{
const confirm=confirm(`try重试?错误:${error}`);
如果(已确认){
此.getDataFromServerInternal(sub);
}
}
);
}

您应该记住在完成时完成并取消订阅所有内容(以避免内存泄漏)。来自组件的调用看起来一样

有趣,我没有想到。但是,如果用户想放弃,我如何将错误案例传递给主题/组件?您可以选择this.tempsuble.error或this.tempsuble.complete-取决于您希望如何继续(在我的示例中,在else部分中,如果确认为false)是的,我忘了!为什么你把tempSubject设为类属性?你从来没有真正使用过它。当然,它可以用来防止多个请求(如果已经定义了,就返回它)。是的,你的建议很有效,而且它是一个添加更多功能的基础设施。如果我的回答对你有帮助,请将它标记为已接受