如何将主线程stdout传入Node.js Worker?解决ora spinner冻结问题
解决ora因主线程阻塞冻结的方案
核心思路:分离阻塞逻辑与UI(ora)
把阻塞的业务逻辑放到Worker线程执行,主线程仅负责管理ora加载动画,这样主线程的事件循环不会被阻塞,ora就能正常播放动画。
代码示例
主线程(index.ts)
import ora from 'ora'; import { Worker } from 'node:worker_threads'; import path from 'node:path'; // 启动ora动画 const spinner = ora('执行任务中...').start(); // 创建Worker处理阻塞任务 const worker = new Worker(path.resolve(__dirname, 'worker.ts')); // 监听Worker的消息 worker.on('message', (msg) => { if (msg.type === 'success') { spinner.succeed('任务完成!'); } else if (msg.type === 'error') { spinner.fail('任务失败:' + msg.error); } }); // 监听Worker错误 worker.on('error', (err) => { spinner.fail('Worker执行出错:' + err.message); }); // 监听Worker退出 worker.on('exit', (code) => { if (code !== 0 && !spinner.isSpinning) { spinner.fail(`Worker异常退出,代码:${code}`); } });
Worker线程(worker.ts)
import { parentPort } from 'node:worker_threads'; // 模拟阻塞任务(比如CPU密集型计算) function blockingJob() { let result = 0; for (let i = 0; i < 1e9; i++) { result += i; } return result; } try { const result = blockingJob(); // 向主线程发送完成消息 parentPort?.postMessage({ type: 'success', data: result }); } catch (err) { parentPort?.postMessage({ type: 'error', error: (err as Error).message }); }
直接将主线程stdout传入Worker的方案
如果确实需要在Worker中使用ora,可以通过传递stdout的文件描述符给Worker,在Worker中重建流并传给ora:
代码示例
主线程(index.ts)
import { Worker } from 'node:worker_threads'; import path from 'node:path'; // 传递stdout的文件描述符给Worker const worker = new Worker(path.resolve(__dirname, 'worker.ts'), { workerData: { stdoutFd: process.stdout.fd } });
Worker线程(worker.ts)
import ora from 'ora'; import { workerData } from 'node:worker_threads'; import { createWriteStream } from 'node:fs'; // 通过文件描述符重建stdout流 const stdoutStream = createWriteStream(null, { fd: workerData.stdoutFd }); // 将流传入ora const spinner = ora({ text: 'Worker中执行任务...', stream: stdoutStream }).start(); // 模拟阻塞任务 setTimeout(() => { spinner.succeed('Worker任务完成!'); process.exit(0); }, 3000);
注意:这种方式下,如果主线程仍然有阻塞逻辑,Worker的输出可能还是会被延迟,因为终端的输出最终还是依赖主线程的事件循环处理。所以优先推荐第一种分离阻塞逻辑到Worker的方案。
内容的提问来源于stack exchange,提问作者Jon Sud
相关产品推荐
相关产品推荐

