RXJS:自适应超时

时间:2018-07-07 10:34:38

标签: 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';

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

有什么帮助吗?

1 个答案:

答案 0 :(得分:1)

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

// source observable simply throws error, which is ideal for testing retry concept
const source = throwError(new Error('Oops..!'));

const smartSource = source.pipe(retryWhen(error => {
return error.pipe(mergeMap((e, i) => {
      const delayFactor = i * i *  1000;
      console.log(`Retrying after ${delayFactor / 1000} seconds`);
      return of('Retry signal').pipe(delay(delayFactor));
}));
}));

smartSource.subscribe(x => console.log('result...'));

如果要更改延迟逻辑,这就像根据需要修改delayFactor一样简单。例如,如果您想每秒重试一次:

const delayFactor = i * 1000;