0

0

如何并行执行多个 Promise 并按原始顺序获取结果

聖光之護

聖光之護

发布时间:2026-02-10 23:17:53

|

171人浏览过

|

来源于php中文网

原创

如何并行执行多个 Promise 并按原始顺序获取结果

本文介绍使用 `promise.all()` 实现 promise 并行执行与顺序返回的高效方案,替代手动维护队列的复杂逻辑,兼顾性能与可读性。

在 JavaScript 异步编程中,一个常见需求是:同时启动多个异步任务(充分利用并发能力),但确保最终结果严格按任务创建/提交的顺序被处理。例如,在持续拉取链上交易日志(getSwaps())的长时运行流程中,每个日志需异步处理(如休眠模拟 I/O、写入数据库),但数据库写入必须保持原始事件顺序,否则将导致数据错乱。

此时,自行实现类似 PromiseQueue 的串行调度器(如问题中基于递归 #dequeue 的类)虽可行,却存在明显缺陷:

  • 违背并发初衷:所有 Promise 实际被强制串行等待,无法并行执行;
  • 逻辑冗余:需手动管理队列、状态、回调链,易出错且难以调试;
  • 资源浪费:长时间运行场景下,内存中堆积未 resolve 的 resolve 函数引用,存在潜在泄漏风险。

正确解法是——Promise.all()。它天然满足两大核心要求:
并行执行:所有传入的 Promise 立即启动(无阻塞等待);
顺序返回:结果数组索引严格对应输入 Promise 的声明顺序(非完成顺序)。

以下为优化后的完整实现:

Kodezi
Kodezi

Kodezi是一个代码助手,帮助完成代码生成、bug修复等。

下载
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function randomNumber(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 模拟异步数据源(替换为实际的 for await...of 逻辑)
async function* getSwaps() {
    for (let i = 0; i < 20; i++) {
        yield { id: i };
    }
}

async function run() {
    const promises = []; // 存储所有待执行的 Promise 实例

    // 【关键】立即创建并推入 Promise(并行启动)
    for await (const log of getSwaps()) {
        const i = log.id;
        const promise = (async () => {
            await sleep(randomNumber(300, 1000)); // 模拟异步处理
            return i; // 返回结果(将按原始顺序出现在结果数组中)
        })();
        promises.push(promise);
    }

    // 【关键】Promise.all 并行等待,结果按 promises 数组索引顺序排列
    try {
        const results = await Promise.all(promises);
        results.forEach((value, index) => {
            console.log(`[Index ${index}] Result:`, value);
            // ✅ 此处可安全执行顺序敏感操作,如写入数据库
            // writeDataToDB(value);
        });
    } catch (error) {
        console.error('At least one promise rejected:', error);
        // 注意:Promise.all 遇任一拒绝即整体拒绝,如需容错请改用 Promise.allSettled
    }
}

run();

⚠️ 重要注意事项

  • 闭包陷阱:示例中 for await 循环内直接使用 log.id 而非循环变量 i(避免经典 var 提升问题),若用普通 for (let i...) 则 let 已确保块级作用域,无需额外处理。
  • 错误处理:Promise.all() 是“全或无”策略——任一 Promise 拒绝,整个调用即拒绝。若需独立处理每个 Promise 的成功/失败状态,请改用 Promise.allSettled(),它始终返回包含 {status, value/reason} 的结果数组。
  • 内存与流控:对“可能运行数小时”的海量数据流(如问题所述),直接累积所有 Promise 到数组可能导致内存溢出。此时应结合分批处理(如每 100 个一组调用 Promise.all)或使用 for await + 限流队列(如 p-map 库),而非完全放弃并行。

✅ 总结

Promise.all() 是解决“并行执行、顺序消费”场景的标准、简洁、高性能方案。它消除了手工队列调度的复杂性,让代码更接近业务意图——专注定义任务,而非调度细节。在保证结果顺序性的前提下,最大化异步并发效率,是现代 JavaScript 异步编程的基石实践之一。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

409

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

586

2023.08.10

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

140

2025.07.29

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

75

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

36

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

64

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

44

2025.11.27

promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

313

2023.10.12

包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法
包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法

本专题汇总了包子漫画官网和网页版入口,提供最新章节抢先看方法、正版免费阅读指南,以及稳定访问方式,帮助用户快速直达包子漫画页面,无广告畅享全集漫画内容。

50

2026.02.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号