首页 > 解决方案 > 如何处理 RxJS 中相互传递数据的子顺序 URL 调用?

问题描述

我有一个服务调用,如果服务器忙于处理响应,它可能会返回给我一个队列 URL。

我正在编写一个有角度的服务来处理这些类型的调用,我正在努力弄清楚什么样的RXJS 6+运营商可以为我处理这个问题。

这意味着我想做一个后备,如果响应返回给我一个排队 URL,我将订阅这个调用,然后重试直到我得到答案。

等待时间最长可达 30 秒 ( < insert frustrations here>)。

从我从 rxjs 文档页面可以看出,我需要使用concatMap操作员,并且以某种方式retry调用,直到我得到正确的响应?也许与一些delay运营商来限制通话量?

我从https://www.learnrxjs.io/找到了这个片段

提前致谢!

标签: angularrxjsangular7angular-httpclientrxjs6

解决方案


这是一个递归调用结构,所以你需要编写一个递归的 observable。你没有提供确切的响应结构,所以我不能给出确切的代码,但在高层次上它看起来像这样:

getQueuedResponse<T>(url) {
  return this.http.get<T>(url).pipe( // fetch the first URL
    switchMap(res => 
      (res.queueUrl) // if queued (your actual queue indicator may be different)
        ? this.getQueuedResponse<T>(res.queueUrl) //then recurse (your actual next url may be different or it may be the original url again)
        : of(res))); // else break (what you actually return here may be different)
}

如果您想使用简单的计时器,可以添加延迟:

getQueuedResponse<T>(url) {
  return this.http.get<T>(url).pipe( // fetch the first URL
    switchMap(res => 
      (res.queueUrl) // if queued, recurse after 5 seconds
        ? timer(5000).pipe(switchMap(t => this.getQueuedResponse<T>(res.queueUrl))
        : of(res))); // else break
}

或者,如果您的需求有点不同,并且您可以一遍又一遍地调用相同的 URL,您可以查看这是一个轮询问题:

pollForResponse<T>(url) {
  return timer(0, 5000).pipe( // start right away then emit every 5 seconds
    switchMap(i => this.http.get<T>(url)), // request the URL
    takeWhile(r => !!r.queued), // keep taking while it's queued
    last() // only emit the last response
  );
}

推荐阅读