如何在包含超时机制的map中获取所有Promise的执行结果
嘿,我来帮你梳理下代码里的问题和解决办法!
首先得说,你的代码里有几个关键问题导致Promise.all没达到预期效果:
await setTimeout完全没用:setTimeout是老派的回调API,它返回的是个定时器ID(数字),不是Promise,所以await对它根本不起作用——这意味着你的延迟逻辑等于没写,而且内部的SendMail调用也不会被正确等待。- 多此一举的外层Promise:Promise.all本身就会返回一个Promise,你没必要再套一层
new Promise(async (resolve, reject) => {...}),这种写法不仅冗余,还容易引发不必要的异步问题。 - 没实现你要的超时机制:你提到需要超时控制,但原代码里完全没处理单个邮件发送或者整体任务的超时逻辑。
正确的实现方案
我们一步步来修正,同时实现你要的间隔执行+超时控制+收集所有结果的需求:
1. 先封装一个可await的延迟函数
把setTimeout转换成Promise,这样才能用await实现正确的延迟:
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
2. 给单个邮件发送任务加超时
用Promise.race实现超时逻辑——如果SendMail在指定时间内没完成,就直接抛出超时错误:
const sendMailWithTimeout = async (item, timeout = 10000) => { return Promise.race([ SendMail(item), // 实际的邮件发送任务 // 超时逻辑:超过timeout毫秒就拒绝 new Promise((_, reject) => { setTimeout(() => reject(new Error(`发送邮件超时: ${JSON.stringify(item)}`)), timeout); }) ]); };
3. 按间隔执行所有任务并收集结果
现在把延迟和带超时的邮件发送结合起来,用Promise.all收集所有结果:
const runMailTasks = async (items) => { try { const allResults = await Promise.all( items.map(async (item, index) => { // 每个任务间隔5秒执行:第一个任务等0秒,第二个等5秒,以此类推 await delay(5000 * index); // 执行带超时的邮件发送 return sendMailWithTimeout(item); }) ); return allResults; } catch (error) { // 捕获任何一个任务的失败或超时 console.error('邮件任务执行出错:', error); throw error; // 可以根据需求决定是否抛出,还是返回错误信息 } }; // 调用示例 runMailTasks(你的邮件列表) .then(results => console.log('所有邮件发送结果:', results)) .catch(err => console.error('整体任务失败:', err));
额外补充:整体任务超时
如果你需要给所有任务的总执行时间加超时(比如所有邮件必须在1分钟内发完),可以在外层再套一层Promise.race:
const runWithTotalTimeout = async (items, totalTimeout = 60000) => { return Promise.race([ runMailTasks(items), new Promise((_, reject) => { setTimeout(() => reject(new Error('整体邮件任务超时,未在规定时间内完成')), totalTimeout); }) ]); };
内容的提问来源于stack exchange,提问作者Meir Peratz
相关产品推荐
相关产品推荐

