RXJS:自适应超时

RXJS:自适应超时,rxjs,timeout,retrywhen,Rxjs,Timeout,Retrywhen,我正在使用RXJS 6,我尝试使用自适应超时进行重试(我第一次尝试使用1s超时,如果不成功,我重试,但使用2s超时,等等) 看起来重试时超时值没有更新,我是RxJS上的新手,我找不到问题 下面是代码片段: import { zip, timer, range, of, pipe } from 'rxjs'; import { tap, retry, concatMap, timeout, catchError, delay, retryWhen } from 'rxjs/operators';

我正在使用RXJS 6,我尝试使用自适应超时进行重试(我第一次尝试使用1s超时,如果不成功,我重试,但使用2s超时,等等)

看起来重试时超时值没有更新,我是RxJS上的新手,我找不到问题

下面是代码片段:

import { zip, timer, range, of, pipe } from 'rxjs';
import {  tap, retry, concatMap, timeout, catchError, delay, retryWhen } from 'rxjs/operators';

let timeoutFactor = 1;
let timeoutInit = 2000;
let timeoutValue = timeoutInit;

// simulate request
function makeRequest(timeToDelay) {  
  return of('Request Complete! '+timeToDelay).pipe(
    tap( () => console.log(`doing request (${timeToDelay}ms) with timeout of ${timeoutValue}`)),
    delay(timeToDelay));
}


const obs$ = of(4000, 3000, 2000)
  .pipe( 
    concatMap(duration => makeRequest(duration).pipe(

      timeout(timeoutValue),
      retryWhen(error => zip(error, range(1,3).pipe(
        tap( i  => {
            console.log("set timeout on " + (i*1000) + " ms")
            setTimeoutFactor(i);
          })
      )))    
    ))
  );

  obs$.subscribe(
    val => console.log(val),
    err => console.log(`err: ${err}` ),
    () => console.log(`complete` ));

  function setTimeoutFactor(value){
    timeoutValue = timeoutInit*value;
  }
但我的结果并不是很好:

doing request (4000ms) with timeout of 2000
set timeout on 1000 ms
set timeout on 2000 ms
set timeout on 3000 ms
doing request (4000ms) with timeout of 6000
doing request (4000ms) with timeout of 6000
doing request (4000ms) with timeout of 6000
doing request (3000ms) with timeout of 6000
timeout: 6000
Request Complete! 3000
doing request (2000ms) with timeout of 6000
timeout: 6000
Request Complete! 2000
complete

有什么帮助吗?

在选择延迟后重试不会那么复杂。例如,指数延迟(1s、4s、9s、16s、25s…)后的以下(测试工作代码)样本重试:

//SourceObservable只是抛出错误,这是测试重试概念的理想选择
const source=throwError(新错误('Oops..!'));
const smartSource=source.pipe(retryWhen)(错误=>{
返回错误。管道(合并映射((e,i)=>{
常数延迟因子=i*i*1000;
log(`在${delayFactor/1000}秒之后重试');
返回(‘重试信号’).pipe(延迟(延迟因子));
}));
}));
订阅(x=>console.log('result…');
如果要更改延迟逻辑,只需根据需要修改
delayFactor
。例如,如果要每秒重试一次:

const delayFactor = i * 1000;

谢谢你的回答。使用“retryBackoff”的cartan的答案在我的情况下更有用。但我保留您的答案以防自定义运算符:)如果没有“timeout”运算符,我不明白如何处理错误。在你的例子中,你抛出了一个错误,但在我的例子中,我不能这样做。我进行http调用,如果延迟超过,则需要抛出错误。我不需要在新呼叫前增加延迟,我需要等待更多时间,等待下一个呼叫:)