点击按钮时重试 Angular http 请求

问题描述

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

组件:

getData() {
    this.apiService.getDataFromServer().subscribe(
        a => console.log(a),b => console.error(b)
    );
}

API 服务:

getDataFromServer() {
    return this.http.get();
}

当请求失败时,我想打开一个用户显示错误的模式。在此模式中,用户找到两个按钮:一个表示“重新加载”,另一个表示“取消”。如果单击其中一个按钮,模态将再次关闭

现在有一种(便宜的)方法来处理这个问题,就是从组件中的错误情况再次调用 getData()。当然,在服务级别处理错误会好得多。这就是我在这里努力实现的目标。


我现在想弄清楚如何处理按钮点击。使用 pipecatchError,不可能在服务方法中“等待”重新加载按钮点击。我认为处理这个问题的好方法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
}

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

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

解决方法

您可以稍微更改设计以获得所需的行为。在中间添加一个主题(而不是从 getDataFromServer 函数返回可观察对象)。

这样,您可以在出现故障时重试服务,如果您将其作为服务的基本功能实现,则可以用它包装每个调用并避免代码重复。

它看起来像:

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

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...