基于Promise实现Rest API冗余调用:优先返回首个200响应
实现方案
要实现你需求的逻辑,核心是优先竞速获取第一个200响应,同时兜底处理全失败的情况,结合AbortController还能主动终止不必要的请求,既优雅又高效。
最终实现代码
async function firstValidOrLastResponse(urls) { const abortController = new AbortController(); const { signal } = abortController; let completedCount = 0; let lastFailedResponse = null; const totalRequests = urls.length; // 为每个请求绑定终止信号 const fetchTasks = urls.map(url => fetch(url, { signal })); return new Promise((resolve) => { fetchTasks.forEach(task => { task.then(response => { completedCount++; // 找到第一个200响应,立即终止其他请求并返回结果 if (response.ok) { abortController.abort(); resolve(response); } else { lastFailedResponse = response; // 所有请求完成且无有效响应,返回最后一个失败结果 if (completedCount === totalRequests) { resolve(lastFailedResponse); } } }).catch(error => { // 忽略主动终止请求的错误 if (error.name === 'AbortError') return; completedCount++; lastFailedResponse = error; if (completedCount === totalRequests) { resolve(lastFailedResponse); } }); }); }); }
逻辑说明
竞速优先逻辑:
- 给所有
fetch请求绑定同一个AbortController信号,一旦某个请求返回200状态码,立即调用abort()终止其余未完成的请求,避免浪费网络资源。 - 第一个符合条件的响应会直接作为最终结果返回,其余请求的后续回调不会干扰结果。
- 给所有
兜底处理逻辑:
- 用
completedCount统计已完成的请求数量,lastFailedResponse记录最后一个非200的响应(包括网络错误)。 - 当所有请求都完成且没有找到200响应时,返回记录的最后一个失败结果。
- 用
垃圾回收优化:
- 主动终止的请求会被浏览器取消,相关的请求资源会被自动回收;已完成但未被引用的响应,JS垃圾回收机制也会自动清理。
使用方式
直接传入需要请求的URL数组即可:
// 示例调用 const urls = ['https://api.example.com/1', 'https://api.example.com/2']; firstValidOrLastResponse(urls) .then(result => { console.log('最终结果:', result); });
这种实现属于异步任务中的**"优先竞速+兜底回退"**模式,在需要从多个异步源获取结果、优先取符合条件的最快结果,否则取兜底结果的场景中非常实用。
内容的提问来源于stack exchange,提问作者wick
相关产品推荐
相关产品推荐

