JavaScript中如何并行运行异步函数,首个resolve后设超时返回结果?
实现带延迟等待的并行Promise处理方案
假设我们有多个调用外部API、响应时间不固定的异步函数:
async function promise1() { /* API 调用 */ } async function promise2() { /* API 调用 */ } async function promise3() { /* API 调用 */ } // ... 直至promiseN
常规的Promise.all()会等待所有Promise完成后返回结果,但我们需要满足以下特殊需求:
- 并行启动所有Promise
- 第一个Promise resolve后,等待500毫秒给其他Promise完成时间
- 超时后忽略未resolve的Promise
- 结果仅包含超时窗口结束前已resolve的内容;若除首个外的其他Promise在超时前全部完成(无论resolve或reject),则立即返回结果
实现代码
async function runWithGracePeriod(promiseFns) { const resultRecords = []; let completedPromiseCount = 0; let hasFirstResolved = false; let graceTimeoutId = null; // 等待触发:要么超时,要么所有Promise都完成 const waitForCompletion = new Promise(resolve => { promiseFns.forEach((promiseFn, idx) => { promiseFn() .then(value => { resultRecords[idx] = { type: 'fulfilled', value }; // 第一个resolve触发后启动500毫秒等待 if (!hasFirstResolved) { hasFirstResolved = true; graceTimeoutId = setTimeout(resolve, 500); } }) .catch(reason => { resultRecords[idx] = { type: 'rejected', reason }; }) .finally(() => { completedPromiseCount++; // 所有Promise都完成时,提前结束等待 if (completedPromiseCount === promiseFns.length) { if (graceTimeoutId) clearTimeout(graceTimeoutId); resolve(); } }); }); }); await waitForCompletion; // 筛选出所有成功resolve的结果 return resultRecords .filter(record => record?.type === 'fulfilled') .map(record => record.value); }
代码说明
- 并行启动Promise:遍历传入的Promise函数数组,立即调用每个函数启动异步任务,确保所有任务并行执行。
- 跟踪第一个resolve:当第一个Promise成功resolve时,启动500毫秒的超时定时器,触发等待窗口的结束。
- 提前结束逻辑:通过
completedPromiseCount统计已完成的Promise数量,当所有Promise都完成时,立即清除定时器并结束等待,无需等到500毫秒超时。 - 结果收集:等待结束后,筛选出所有在窗口内成功resolve的结果返回,忽略reject或未完成的Promise。
使用示例
// 传入异步函数数组(注意是函数,不是已执行的Promise) const targetPromises = [promise1, promise2, promise3]; runWithGracePeriod(targetPromises).then(finalResults => { console.log('最终返回的成功结果:', finalResults); });
特殊情况处理
- 如果所有Promise都reject:会立即返回空数组,因为所有Promise完成后触发提前结束,筛选后无成功结果。
- 如果第一个完成的是reject:会继续等待第一个resolve的Promise出现,再启动500毫秒等待窗口;若始终没有Promise resolve,最终返回空数组。
内容的提问来源于stack exchange,提问作者philosopher
相关产品推荐
相关产品推荐

