试图理解这个retryWhen/scan/delay rxjs序列
因此,我提出了一个HTTP请求延迟重试的实现,它工作得很好,我对它也有很好的理解试图理解这个retryWhen/scan/delay rxjs序列,rxjs,Rxjs,因此,我提出了一个HTTP请求延迟重试的实现,它工作得很好,我对它也有很好的理解 retryWhen(err => { let retryCount = 0; let nextDelay = 0; backoff = backoff < 0 || backoff === null ? DEFAULT_BACKOFF : backoff; maxDelay = maxDelay < 0 || maxDelay === null ? DEFAULT_
retryWhen(err => {
let retryCount = 0;
let nextDelay = 0;
backoff = backoff < 0 || backoff === null ? DEFAULT_BACKOFF : backoff;
maxDelay = maxDelay < 0 || maxDelay === null ? DEFAULT_MAX_DELAY : maxDelay;
return err.pipe(
scan(idx => {
if (idx > maxRetries - 1) {
throw err;
} else {
idx++;
retryCount = idx;
nextDelay = Math.min(retryDelay + ((retryCount - 1) * backoff), maxDelay);
return idx;
}
}, 0),
tap(v => console.log(`Waiting ${nextDelay} ms for Retry #${retryCount}...`)),
delay(nextDelay),
tap(v => console.log(`Initiating HTTP Retry for context ${context}`))
)
扫描将原始的
err
元素映射到索引idx
,但是如何在delay
操作符中准确地得到它呢?传递给retryWhen的函数在第一个错误时只调用一次。因此,在创建可观察的err.pipe(…)
时(而不是在err
发出时),会调用一次delay(nextDelay)
。当时nextDelay
仍然是0
。您应该将所有逻辑放在一个运算符中,该运算符根据err
发出的值返回不同的值
要返回发射延迟变化的可见光,您可以将mergeMap
映射到计时器。这应该让你开始:
接口RetryStrategyConfig{
maxRetryAttempts?:数字;
缩放持续时间?:数字;
maxDelay?:数字;
excludedStatusCodes?:编号[];
}
功能通用系统策略({
maxRetryAttempts=6,
缩放持续时间=1000,
最大延迟=5000,
excludedStatusCodes=[]
}:RetryStrategyConfig={}){
返回(尝试次数:可观察)=>{
回流管(
合并映射((错误,i)=>{
const retrytry=i+1;
//如果已达到最大重试次数
//或者响应是我们不希望重试的状态代码,抛出错误
如果(
重试次数>最大重试次数||
excludedStatusCodes.find(e=>e==error.status)
) {
返回投掷器(错误);
}
const nextDelay=Math.min(重试*缩放持续时间,最大延迟);
log(`trunt${retrytrunt}:在${nextDelay}ms`中重试);
返回计时器(下一个延迟);
}),
完成(()=>console.log(“我们完成了!”)
);
};
}
obs美元管道(
retryWhen(genericRetryStrategy())
)
传递给retryWhen的函数在第一个错误时只调用一次。因此,在创建可观察的err.pipe(…)
时(而不是在err
发出时),会调用一次delay(nextDelay)
。当时nextDelay
仍然是0
。您应该将所有逻辑放在一个运算符中,该运算符根据err
发出的值返回不同的值
要返回发射延迟变化的可见光,您可以将mergeMap
映射到计时器。这应该让你开始:
接口RetryStrategyConfig{
maxRetryAttempts?:数字;
缩放持续时间?:数字;
maxDelay?:数字;
excludedStatusCodes?:编号[];
}
功能通用系统策略({
maxRetryAttempts=6,
缩放持续时间=1000,
最大延迟=5000,
excludedStatusCodes=[]
}:RetryStrategyConfig={}){
返回(尝试次数:可观察)=>{
回流管(
合并映射((错误,i)=>{
const retrytry=i+1;
//如果已达到最大重试次数
//或者响应是我们不希望重试的状态代码,抛出错误
如果(
重试次数>最大重试次数||
excludedStatusCodes.find(e=>e==error.status)
) {
返回投掷器(错误);
}
const nextDelay=Math.min(重试*缩放持续时间,最大延迟);
log(`trunt${retrytrunt}:在${nextDelay}ms`中重试);
返回计时器(下一个延迟);
}),
完成(()=>console.log(“我们完成了!”)
);
};
}
obs美元管道(
retryWhen(genericRetryStrategy())
)
第一个问题:当我在delay操作符中使用一个常量值(如so delay(3000))时,上面的代码可以正常工作,但当我使用nextDelay变量时,它不能正常工作。当我使用nextDelay变量时,没有延迟,就像变量为零一样
这一问题的原因已经在报告中指出
但是,该值在tap运算符中正确输出
这暗示着你可以解决它。区别在于delay(value)
捕获值
,在点击(()=>…)
的情况下,每次调用其回调函数时(在本例中,每次下一次通知时),都会对值
进行评估
如果我们看看
导出函数延迟(到期日期:number |日期,调度程序:SchedulerLike=asyncScheduler):MonoTypeOperatorFunction{
const duration=计时器(到期,调度程序);
返回delayWhen(()=>持续时间);
}
我们将看到它首先捕获计时器
可观察值中的值,然后与delayWhen
一起使用
因此,第一个问题可以通过以下方式解决:
/**/
轻触(v=>console.log(`Waiting${nextDelay}ms for Retry#${retryCount}…`)),
延迟时间(()=>计时器(下一个延迟)),
轻触(v=>console.log(`Initiating HTTP Retry for context${context}`))
/* ... */
第二个问题:我想优化上面的代码,这样我就不会使用变量retryCount和nextDelay
我们可以使用其他RxJS操作符来实现这一点:
retryWhen(err=>{
退避=退避<0 | |退避===null?默认值_退避:退避;
maxDelay=maxDelay<0 | | maxDelay===null?默认值_MAX_DELAY:maxDelay;
返回错误管道(
//将'retryCount'替换为'map'的索引参数
映射((错误,idx)=>{
//您也可以在这里抛出错误
如果(idx>=maxRetries){throw err;}
const retryCount=idx+1;
//返回'nextDelay'`
返回Math.min(retryDelay+((retryCount-1)*退避),maxDelay;
})
延迟时间(nextDelay=>timer(nextDelay)),
)
第一个问题:当我在delay操作符中使用一个常量值(如so delay(3000))时,上面的代码可以正常工作,但当我使用nextDelay变量时,它不能正常工作。当我使用nextDelay变量时,没有延迟,就像变量为零一样
问题的原因已在中指出。scan(idx => ... code to either throw the error or emit the index ...),
delay(idx => Math.min(retryDelay + (idx - 1) * backoff), maxDelay)