恢复连接后按时间顺序重试请求

Chronologically retry requests after restoring connection

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

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

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

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

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

程序上

Information stored in stack not sent > Connection comes back > Stack Items sent 1 by 1 > Each response will set a next(data) to the BehaviorSubject which will be Observed by the Components > Each change in value will be reflected by your Components

我会尝试这样的事情:

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

网络-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 数组中的位置重试请求。