如何组合三个Promise并行执行,任意两个resolved时触发最终Promise?
嘿,这个需求挺有意思的!要实现三个Promise并行执行,只要任意两个resolve就触发最终Promise的resolve,我有两种实用的方案分享给你:
方案一:手动计数实现(灵活可控)
这种方法适合需要更精细控制的场景,比如要记录所有resolved的值,或者处理特殊的边界情况:
function resolveOnTwo(promises) { return new Promise((finalResolve, finalReject) => { let resolvedCount = 0; const resolvedResults = []; let totalPromises = promises.length; let rejectedCount = 0; // 遍历每个Promise,监听状态 promises.forEach((promise, idx) => { // 确保处理非Promise类型的值 Promise.resolve(promise) .then(result => { resolvedCount++; resolvedResults[idx] = result; // 当有两个Promise resolve时,立刻触发最终resolve if (resolvedCount === 2) { // 返回已resolve的结果(过滤掉未定义的项) finalResolve(resolvedResults.filter(item => item !== undefined)); } }) .catch(err => { rejectedCount++; // 所有Promise都处理完,但resolve的数量不足2时,触发reject if (resolvedCount + rejectedCount === totalPromises && resolvedCount < 2) { finalReject(new Error("不足2个Promise成功resolve")); } }); }); }); }
用法示例:
// 模拟三个异步操作 const promise1 = new Promise(resolve => setTimeout(() => resolve("结果1"), 1000)); const promise2 = new Promise(resolve => setTimeout(() => resolve("结果2"), 500)); const promise3 = new Promise((resolve, reject) => setTimeout(() => reject("失败3"), 1500)); resolveOnTwo([promise1, promise2, promise3]) .then(results => console.log("成功!得到两个结果:", results)) // 会在1000ms时输出 ["结果1", "结果2"] .catch(err => console.error("错误:", err));
方案二:利用Promise.all + Promise.race(简洁优雅)
如果你的场景比较简单,这个方案更清爽——通过生成所有两两Promise的组合,用Promise.all等待每组的两个都resolve,再用Promise.race取第一个完成的组合:
function resolveOnTwo(promises) { // 生成所有两两组合的Promise数组 const pairs = []; for (let i = 0; i < promises.length; i++) { for (let j = i + 1; j < promises.length; j++) { pairs.push([promises[i], promises[j]]); } } // 用race等待第一个完成的两两组合(即第一个有两个Promise都resolve的组合) return Promise.race(pairs.map(pair => Promise.all(pair))); }
用法示例:
const promise1 = new Promise(resolve => setTimeout(() => resolve("结果1"), 1000)); const promise2 = new Promise(resolve => setTimeout(() => resolve("结果2"), 500)); const promise3 = new Promise(resolve => setTimeout(() => resolve("结果3"), 1500)); resolveOnTwo([promise1, promise2, promise3]) .then(results => console.log("成功!得到两个结果:", results)) // 同样在1000ms时输出 ["结果1", "结果2"] .catch(err => console.error("错误:", err));
两种方案对比:
- 方案一:可以灵活控制结果的收集方式,比如保留所有resolve的结果(哪怕超过两个),也能清晰处理“最终不足两个resolve”的错误场景,适合复杂需求。
- 方案二:代码更简洁,利用原生Promise API实现,可读性高,但当Promise数量很多时,两两组合的数量会指数级增长,性能会受影响(不过你只有三个Promise,完全不用担心)。
内容的提问来源于stack exchange,提问作者Kunal
相关产品推荐
相关产品推荐

