JavaScript并行处理Promise:实现超时提前返回前两个完成结果的逻辑
JavaScript并行处理Promise:实现超时提前返回前两个完成结果的逻辑
看起来你已经理清了基本需求,但确实,用Promise.all的话会卡死在等待所有Promise完成,没法实现“超时就提前返回前两个结果”的逻辑。我来帮你调整一下思路和代码:
你原来的代码是等所有Promise都跑完了才判断耗时,这时候已经错过了提前返回的时机——毕竟如果有一个Promise要跑100ms,你得等它跑完才能知道总耗时超过50ms,但这时候用户已经等了100ms了,完全不符合需求里“返回前两个可用结果”的要求。
我们需要换个思路:同时监听两个事件,要么所有Promise在50ms内全部完成,要么超时后立刻去拿前两个完成的结果。下面是完整的实现方案:
function getPromise(): Promise<number> { return new Promise(resolve => { setTimeout(()=>{ resolve(Math.round(Math.random() * 10)) }, Math.random() * 100); }) }; // 辅助函数:等待数组中前n个完成的Promise,返回它们的结果数组 function waitForN<T>(promises: Promise<T>[], n: number): Promise<T[]> { return new Promise((resolve) => { let completedCount = 0; const results: T[] = []; promises.forEach(promise => { promise.then(result => { // 只收集前n个完成的结果 if (completedCount < n) { results.push(result); completedCount++; // 收集够n个就立刻resolve,不等剩下的Promise if (completedCount === n) { resolve(results); } } }); }); }); } const TIMEOUT_MS = 50; async function foo(){ // 同步创建三个Promise,满足第一个要求 const promises = [getPromise(), getPromise(), getPromise()]; // 定义一个50ms的超时信号Promise const timeoutSignal = new Promise(resolve => { setTimeout(() => resolve('timeout'), TIMEOUT_MS); }); try { // 让"所有Promise完成"和"超时"两个事件竞争 const raceWinner = await Promise.race([ Promise.all(promises), // 所有Promise完成的话,返回结果数组 timeoutSignal // 超时的话,返回标记字符串 ]); if (raceWinner === 'timeout') { // 超时了,等待前两个完成的Promise并返回它们的和 const firstTwoResults = await waitForN(promises, 2); return firstTwoResults.reduce((sum, num) => sum + num, 0); } else { // 所有Promise都在50ms内完成,返回三个数的总和 return raceWinner.reduce((sum, num) => sum + num, 0); } } catch (error) { // 处理Promise失败的情况(题目说明都是fulfill,这里可选保留) console.error('Promise执行出错:', error); throw error; } }
关键逻辑解释:
- 同步创建Promise:
promises数组是一次性初始化的三个Promise,它们会立刻启动内部的定时器,完全满足“同步创建”的要求。 - Promise.race的作用:它会等待第一个完成的Promise——如果三个Promise都在50ms内跑完,
Promise.all(promises)会先胜出,我们直接计算总和;如果50ms到了还有Promise没跑完,timeoutSignal先触发,我们就立刻切换到“取前两个结果”的逻辑。 - waitForN辅助函数:这个函数会监听所有Promise的完成状态,一旦收集到前N个结果就立刻resolve,不会等待剩下的Promise,完美契合“返回前两个可用结果”的需求。
你可以测试两种场景:
- 当三个Promise的定时器都小于50ms时,会直接返回三个数的总和;
- 当有一个或多个Promise的定时器超过50ms时,超时信号会先触发,随后返回前两个完成的Promise的结果之和。
备注:内容来源于stack exchange,提问作者Evanss
相关产品推荐
相关产品推荐

