ES6:在Promise中按条件触发重试直至达到最大重试次数
基于响应条件的Promise灵活重试方案
这确实是个比普通固定重试更贴合实际业务的需求——毕竟很多场景下,咱们不能不管三七二十一就重试,得根据请求返回的结果来决定下一步动作。下面我给你写一个可扩展、基于策略配置的重试实现,完美匹配你提到的场景。
核心思路
把「判断条件」和「对应操作」拆成可配置的策略,主重试函数负责执行目标Promise、循环匹配策略并处理,直到达到最大重试次数或者触发终止条件。
代码实现
首先,先封装一个基于XMLHttpRequest的Promise请求函数(模拟你的场景):
function makeXHRRequest(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = () => { // 把状态码和响应内容一起返回,方便后续判断 resolve({ status: xhr.status, responseText: xhr.responseText }); }; xhr.onerror = () => reject(new Error('XHR请求失败')); xhr.send(); }); }
然后是核心的重试函数,支持自定义策略:
async function retryWithStrategy( taskFn, // 要执行的Promise任务函数 maxRetries, // 最大重试次数 strategies // 重试策略数组 ) { let retryCount = 0; while (retryCount <= maxRetries) { try { const result = await taskFn(); // 遍历策略,找到匹配的规则 const matchedStrategy = strategies.find(strategy => strategy.condition(result)); if (!matchedStrategy) { // 没有匹配到策略,默认返回结果 return result; } // 执行策略对应的操作 const actionResult = await matchedStrategy.action(result); if (actionResult === 'reject') { // 策略要求拒绝,直接抛出错误 throw new Error(`触发拒绝策略: ${result.status}`); } else if (actionResult === 'retry') { // 策略要求重试,计数加1,继续循环 retryCount++; console.log(`触发重试策略,当前重试次数: ${retryCount}`); } else { // 策略返回了新的结果,直接返回 return actionResult; } } catch (error) { // 捕获到错误,直接拒绝 throw error; } } // 达到最大重试次数,拒绝 throw new Error(`已达到最大重试次数: ${maxRetries}`); }
配置你的专属策略
根据你的需求,配置对应的策略规则:
const customStrategies = [ // 状态码200:解析Promise,返回结果 { condition: (result) => result.status === 200, action: (result) => result }, // 状态码299:立即重试 { condition: (result) => result.status === 299, action: () => 'retry' }, // 状态码399:立即拒绝 { condition: (result) => result.status === 399, action: () => 'reject' }, // 状态码499:先从服务器获取内容再重试 { condition: (result) => result.status === 499, async action() { console.log('先从服务器获取额外内容...'); // 模拟获取额外内容的请求 const extraData = await fetch('/api/get-extra-content').then(res => res.json()); console.log('获取到额外内容:', extraData); // 返回重试信号 return 'retry'; } } ];
调用示例
// 模拟一个会返回不同状态码的请求 function mockRequest() { // 这里可以根据重试次数模拟不同状态,比如第一次返回499,第二次返回299,第三次返回200 let callCount = 0; return () => { callCount++; if (callCount === 1) return Promise.resolve({ status: 499 }); if (callCount === 2) return Promise.resolve({ status: 299 }); return Promise.resolve({ status: 200, responseText: '成功数据' }); }; } // 执行重试 retryWithStrategy(mockRequest(), 3, customStrategies) .then(res => console.log('最终结果:', res)) .catch(err => console.error('请求失败:', err));
扩展性说明
这个方案的扩展性很强,你可以轻松扩展:
- 给策略加重试间隔:比如在返回'retry'前加
await new Promise(resolve => setTimeout(resolve, 1000)) - 支持更复杂的判断条件:比如根据响应体内容、错误类型来判断
- 自定义重试次数:给不同策略配置不同的最大重试次数
- 增加日志、监控:在策略执行前后加入日志打点
内容的提问来源于stack exchange,提问作者sookie
相关产品推荐
相关产品推荐

