RXJS:自适应超时

RXJS: adaptative timeout

我正在使用 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 ...)后重试:

// 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;