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

TypeScript中async/await并行执行异常问题求助

问题分析与解决

核心问题拆解

  1. 串行执行的原因:

    • 你的compute函数虽然标记为async,但内部的质数查找逻辑是纯同步阻塞代码,JavaScript单线程模型下,同步代码会占据事件循环,导致三个compute任务只能依次执行,无法并行。
    • handle函数里用forEach调用compute,但forEach不会等待异步函数完成,而且同步阻塞的计算逻辑直接阻塞了主线程,根本没有并行的机会。
  2. AssertionError参数错误:

    • new AssertionError()必须传入一个配置对象参数(比如包含message属性),直接调用会触发类型错误,这是你看到ERR_INVALID_ARG_TYPE的原因。

解决方案

1. 修复AssertionError参数

首先修正错误抛出的代码,给AssertionError传入合法的配置对象:

throw new AssertionError({ message: `已找到${n}个质数,触发错误` });

2. 实现真正的并行执行

由于JavaScript单线程的限制,同步阻塞计算无法在主线程并行,必须使用Worker线程(Node.js中使用worker_threads模块)来实现多线程并行计算。

完整改造代码

主文件(index.ts):

import { AssertionError } from 'assert';
import { Worker } from 'worker_threads';

// 创建Worker线程执行质数计算
function createComputeWorker(n: number): Promise<void> {
  return new Promise((_, reject) => {
    const worker = new Worker('./compute-worker.ts', { workerData: n });
    
    worker.on('message', (prime) => {
      console.log(`found prime: ${prime}`);
    });
    
    worker.on('error', reject);
    
    worker.on('exit', (code) => {
      if (code !== 0) {
        reject(new AssertionError({ message: `线程执行完成,找到${n}个质数` }));
      }
    });
  });
}

async function handle(numbers: Array<number>) {
  // 使用Promise.race,第一个完成(或出错)的任务会立即触发结果
  await Promise.race(numbers.map(n => createComputeWorker(n)));
}

async function main() {
  try {
    await handle([1000, 1000, 5]);
  } catch (err) {
    console.error(err);
  }
}

main();

Worker文件(compute-worker.ts):

import { parentPort, workerData } from 'worker_threads';

const n = workerData as number;

function isPrime(p: number): boolean {
  if (p <= 1) return false;
  if (p === 2) return true;
  // 优化isPrime逻辑,原来的双重循环效率极低,这里改成只遍历到平方根
  for (let i = 2; i <= Math.sqrt(p); i++) {
    if (p % i === 0) return false;
  }
  return true;
}

let primesFound = 0;
for (let p = 2; primesFound < n; p++) {
  if (isPrime(p)) {
    parentPort?.postMessage(p);
    primesFound++;
  }
}

// 任务完成,退出线程
process.exit(1); // 用非0退出码标识任务完成,触发主进程的reject

3. 关键改进点说明

  • Worker线程:把质数计算逻辑放到独立线程,三个任务可以真正并行执行,不会阻塞主线程。
  • Promise.race:替代forEach,让第一个完成(或抛出错误)的任务立即终止等待,符合你“耗时最短的任务最先触发错误”的需求。
  • isPrime优化:原来的双重循环效率极低,改成遍历到平方根,大幅提升计算速度。

运行结果

改造后,查找5个质数的任务会最先完成并抛出错误,控制台会先输出前5个质数,然后立即打印AssertionError,不会等待另外两个任务完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 15:15:27