You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js有限并行性存疑:示例代码是否真的实现并行?

关于Node.js异步流控制示例的疑问解答

你完全没理解错——这段代码根本不是并行执行的,官方文档这里的描述明显有问题,这就是个标准的串行执行逻辑。

为什么是串行?

看核心的serial函数逻辑:每次调用dispatch发送邮件后,只有等到它的异步回调执行完毕,才会再次调用serial发起下一次邮件发送。也就是说,同一时间永远只有一个sendMail请求在运行,必须等上一个彻底完成,才会启动下一个,完全是串行的执行流程,和“有限并行”没有任何关系。

原示例代码

let successCount = 0;

function final() {
  console.log(`dispatched ${successCount} emails`);
  console.log('finished');
}

function dispatch(recipient, callback) {
  // `sendEmail` is a hypothetical SMTP client
  sendMail(
    {
      subject: 'Dinner tonight',
      message: 'We have lots of cabbage on the plate. You coming?',
      smtp: recipient.email,
    },
    callback
  );
}

function sendOneMillionEmailsOnly() {
  getListOfTenMillionGreatEmails(function (err, bigList) {
    if (err) throw err;

    function serial(recipient) {
      if (!recipient || successCount >= 1000000) return final();
      dispatch(recipient, function (_err) {
        if (!_err) successCount += 1;
        serial(bigList.pop());
      });
    }

    serial(bigList.pop());
  });
}

sendOneMillionEmailsOnly();

真正的有限并行实现思路

如果要实现有限并行(比如同时最多运行5个邮件发送任务),需要维护一个“任务池”,当一个任务完成后立刻补充新的任务,保持并行数量在设定的上限。简单示例如下:

let successCount = 0;
const MAX_PARALLEL_TASKS = 5; // 控制最大并行数
let activeTaskCount = 0;
let currentListIndex = 0;

function final() {
  console.log(`dispatched ${successCount} emails`);
  console.log('finished');
}

function dispatch(recipient, callback) {
  sendMail(
    {
      subject: 'Dinner tonight',
      message: 'We have lots of cabbage on the plate. You coming?',
      smtp: recipient.email,
    },
    callback
  );
}

function sendOneMillionEmailsWithLimit() {
  getListOfTenMillionGreatEmails(function (err, bigList) {
    if (err) throw err;

    function runNextTask() {
      // 终止条件:已发送够100万,或者列表已遍历完,且所有活跃任务都结束
      if (successCount >= 1000000 || currentListIndex >= bigList.length) {
        if (activeTaskCount === 0) final();
        return;
      }

      activeTaskCount++;
      const recipient = bigList[currentListIndex++];
      
      dispatch(recipient, function (_err) {
        activeTaskCount--;
        if (!_err) successCount += 1;
        runNextTask(); // 当前任务完成,立刻启动下一个
      });
    }

    // 初始化启动最大并行数的任务
    for (let i = 0; i < MAX_PARALLEL_TASKS; i++) {
      runNextTask();
    }
  });
}

sendOneMillionEmailsWithLimit();

内容的提问来源于stack exchange,提问作者Truc Truca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:32:16