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

如何将主线程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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 05:46:10