【问题标题】:Chronologically retry requests after restoring connection恢复连接后按时间顺序重试请求
【发布时间】:2021-07-01 23:21:29
【问题描述】:

如何在用户没有互联网连接时“堆叠”正在进行的请求,并在再次上网后按时间顺序重试

我不能在拦截器中使用“纯”retryWhen,因为每个 intercept() 调用都不知道其他请求(我认为)。

我尝试使用拦截器在离线模式下接收请求,将它们添加到数组(作为 Observables,类似于this.offlineRequests.push(next.handle(request))),最后在重新建立连接时重新订阅它们。但问题是我的组件没有得到响应。我的意思是请求正在发出,但看起来组件已经得到 error 并且它不在乎,我稍后在某个地方订阅了 next.handle()。

【问题讨论】:

    标签: angular rxjs angular-http-interceptors


    【解决方案1】:

    我会尝试这样的:

    offline.interceptor.ts

    class OfflineInterceptor implements HttpInterceptor {  
      constructor (private networkStatusService: NetworkStatusService) {}
      
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req).pipe(
          catchError(err => {
            // At this point, we must return an observable.
            return concat(
              // We're first waiting for the connection to become available.
              // `ignoreElements` - will ignore `next` notifications. But it will let `error/complelete`
              // notifications pass through.
              this.networkStatusService.isOnline$.pipe(first(), ignoreElements()),
              // After we're back online, we make the request once again.
              next.handle(req),
            )
          })
        );
      }
    }
    

    network-status.service.ts

    class NetworkStatusService {
      private networkStatus = new Subject<boolean>();
    
      get isOnline$ () {
        return this.networkStatus.pipe(
          filter(Boolean)
        );
      }
    }
    

    因此,当没有互联网连接时,订阅将处于某种 待定状态,直到连接重新建立。注意concat 的第一个参数:

    return concat(
      // !
      this.networkStatusService.isOnline$.pipe(first()),
      next.handle(req),
    )
    

    本质上发生的事情是networkStatus Subject 实例将有一个新订阅者。并且由于每次请求因连接不良而失败时都会发生这种情况,因此将尊重新订阅者的顺序。所以,如果我们有这样的东西(按顺序):

    // In `Component1` - this fails first.
    this.http.get(...);
    
    // In `Component2` - this fails second.
    this.http.get(...);
    
    // In `Component3` - this fails third.
    this.http.get(...);
    

    networkStatus' 的订阅者将是(大致 - 有更多的事情发生,但这个概念仍然成立):

    // networkStatus.subscribers
    [
      SubscriberThatCorrespondsToComp1Subscriber,
      SubscriberThatCorrespondsToComp2Subscriber,
      SubscriberThatCorrespondsToComp3Subscriber,
    ]
    

    这意味着当连接恢复在线时,将根据它们在networkStatus.subscribers 数组中的位置重试请求。

    【讨论】:

      【解决方案2】:

      如果我清楚你的问题,你不想存储请求(就像你已经做的那样),而是让组件等待响应而不是在发生超时错误时出错。

      使用 Behavior 主题来存储 LAST 发出的响应,然后您将观察它以触发组件的状态。 使用它意味着即使您的组件由于超时而出错,当连接恢复时,将重新发送的堆栈将每个操作 BehaviourSubject 的最后状态,从而使用新信息重新渲染组件。

      程序上

      存储在堆栈中的信息未发送 > 连接返回 > 堆栈项目逐个发送 > 每个响应都会为 BehaviorSubject 设置一个下一个(数据),组件将观察它 > 每个值的变化都将由您的组件

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多