TypeScript中async/await并行执行异常问题求助
问题分析与解决
核心问题拆解
串行执行的原因:
- 你的
compute函数虽然标记为async,但内部的质数查找逻辑是纯同步阻塞代码,JavaScript单线程模型下,同步代码会占据事件循环,导致三个compute任务只能依次执行,无法并行。 handle函数里用forEach调用compute,但forEach不会等待异步函数完成,而且同步阻塞的计算逻辑直接阻塞了主线程,根本没有并行的机会。
- 你的
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
相关产品推荐
相关产品推荐

