Angular 如何处理RxJS中相互传递数据的子顺序URL调用?

Angular 如何处理RxJS中相互传递数据的子顺序URL调用?,angular,rxjs,angular7,angular-httpclient,rxjs6,Angular,Rxjs,Angular7,Angular Httpclient,Rxjs6,我调用了一个服务,如果服务器忙于处理响应,它可能会向我返回一个队列URL 我正在用angular编写一个服务来处理这些类型的调用,我正在努力找出哪种RXJS 6+操作符来为我处理这些调用 这意味着我想做一个回退,如果响应返回给我一个排队URL,我将订阅这个调用,并重试,直到得到答案 等待时间最长可达30秒() 从rxjs文档页面可以看出,我需要使用concatMap操作符,然后以某种方式重试调用,直到得到正确的响应?可能需要一些延迟操作员来限制呼叫量 这是我从你的房间里找到的 提前谢谢 如果我的

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

我正在用angular编写一个服务来处理这些类型的调用,我正在努力找出哪种
RXJS 6+
操作符来为我处理这些调用

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

等待时间最长可达30秒(

从rxjs文档页面可以看出,我需要使用
concatMap
操作符,然后以某种方式
重试调用,直到得到正确的响应?可能需要一些
延迟
操作员来限制呼叫量

这是我从你的房间里找到的


提前谢谢

如果我的假设不正确,我会回来编辑此内容,但假设在您需要将请求重定向到队列时,您返回的负载与此类似:

{
    queue: true
    url: "http://myqueue.com"
}
vs当您刚刚收到响应时:

{
    queue: false
    data: { "foo": "bar" }
}
重定向请求的方法可能如下所示

http.get<DataModel>('http://the-original-url').pipe(
    switchMap(dataModel=>{
        //did we get queued?
        if (dataModel.queue) {
            //make a subsequent request and retry it 3 times
            return http.get<QueueResponseModel>(dataModel.url).pipe(retry(3))
        } else {
            //return an observable that emits the desired data
            return of(dataModel.data)
        }
    })
)
http.get('http://the-original-url)。烟斗(
开关映射(数据模型=>{
//我们排队了吗?
if(dataModel.queue){
//发出后续请求并重试3次
返回http.get(dataModel.url).pipe(重试(3))
}否则{
//返回发出所需数据的可观察对象
返回(dataModel.data)
}
})
)

这是一个递归调用结构,因此您需要编写一个递归可观察对象。您没有提供准确的响应结构,因此我无法给出准确的代码,但在较高的级别上,它将如下所示:

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(url){
返回此.http.get(url).pipe(//获取第一个url
开关映射(res=>
(res.queueUrl)//如果排队(实际队列指示符可能不同)
?this.getQueuedResponse(res.queueUrl)//然后递归(您的实际下一个url可能不同,或者可能再次是原始url)
:of(res));//否则中断(您实际返回的内容可能不同)
}
如果您想使用简单的计时器,可以添加延迟:

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
}
getQueuedResponse(url){
返回此.http.get(url).pipe(//获取第一个url
开关映射(res=>
(res.queueUrl)//如果排队,则在5秒后递归
?计时器(5000).管道(开关映射(t=>this.getQueuedResponse(res.queueUrl))
:of(res));//否则断开
}
或者,如果您的需求稍有不同,您可以反复调用相同的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
  );
}
pollForResponse(url){
返回计时器(0,5000)。管道(//立即启动,然后每5秒发出一次
switchMap(i=>this.http.get(url)),//请求url
takeWhile(r=>!!r.queued),//在排队时继续拍摄
last()//只发出最后一个响应
);
}

您是否有任何关于您目前所处位置的代码?另外还有一个潜在响应负载的示例。这些代码将帮助您获得更快的答案。