递归实现Web请求Promise竞态超时重试的逻辑异常排查
Web请求超时竞态重试问题排查
问题场景
开发过程中遇到Web请求响应耗时波动较大的问题:部分请求0.1秒即可完成响应,部分请求耗时长达20秒。
初始设计思路
- 为请求配置固定超时阈值,超时触发后立即发起新的请求
- 保留所有之前未完成的pending状态请求,让所有在途请求共同参与竞态
- 任意一个请求成功完成后,立即终止整个竞态流程,终止其余未完成请求的处理逻辑
- 同时欢迎针对该场景提供更优的替代实现方案
当前实现代码
const timeoutLimit = 300; const timeoutMessage = 'Response timed out'; /** Executes a request, retrying on timeouts, until it returns successfully. */ export default async function requestWithTimeout(request, count) { const timeout = new Promise((resolve, reject) => { setTimeout(() => reject(timeoutMessage), timeoutLimit); }); const apiCall = new Promise((resolve, reject) => { request .catch((err) => reject(err)) .then((resp) => resolve(resp)); }); count += 1; const result = await Promise.race([apiCall, timeout]) .catch((err) => { console.log(err, count); return (err === timeoutMessage) ? Promise.race([apiCall, requestWithTimeout(request, count)]) : err; }) .then((val) => { console.log('returned', count); return val; }); console.log(count, result); return result; }
运行异常表现
当前代码运行后,控制台始终输出如下顺序的日志,所有请求按递归嵌套顺序依次返回,无法在首个请求完成时立即终止竞态流程:
Response timed out 1 Response timed out 2 returned 1 returned 2 returned 3 data 1 data 2 data 3
预期的正确日志输出顺序如下(首个请求成功后立刻结束整体流程,其余已发起请求按实际完成顺序打印日志即可):
Response timed out 1 Response timed out 2 returned 1 data 1 returned 3 data 3 returned 2 data 2
待解决问题
排查现有代码无法实现预期竞态效果的根因,给出可运行的修正方案,也可提供更优的替代实现。
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

