Skip to main content
Worker API 仍处于实验阶段(特别是在终止 worker 方面)。我们正在积极改进。
通过 Worker,您可以启动并与运行在单独线程上的新 JavaScript 实例通信,同时与主线程共享 I/O 资源。 Bun 实现了 Web Workers API 的最小版本,并添加了使其更适合服务端使用场景的扩展。与 Bun 的其他部分一样,Worker 支持 CommonJS、ES 模块、TypeScript、JSX 和 TSX,无需额外的构建步骤。

创建 Worker

与浏览器中一样,Worker 是一个全局对象。使用它来创建一个新的 worker 线程。

从主线程

index.ts

Worker 线程

worker.ts
为防止在使用 self 时出现 TypeScript 错误,请在 worker 文件顶部添加此行。
您可以在 worker 代码中使用 import 和 export 语法。与浏览器不同,您不需要传递 {type: "module"} 来使用 ES 模块。 如果 worker 的脚本解析失败,Worker 对象上会发出 "error" 事件。
传递给 Worker 的说明符相对于项目根目录进行解析(类似于在终端中键入 bun ./path/to/file.js)。

preload - 在 worker 启动前加载模块

将模块说明符数组传递给 preload 选项,可在 worker 自身代码运行之前加载它们,类似于 --preload CLI 参数。用于必须优先加载的代码,例如 OpenTelemetry、Sentry 或 DataDog。
index.ts
您也可以将单个字符串传递给 preload 选项:
index.ts

blob: URL

您也可以将 blob: URL 传递给 Worker,以从字符串或其他内存源码创建 worker。
与 Bun 的其他部分一样,从 blob: URL 创建的 worker 支持 TypeScript、JSX 和其他文件类型。要告诉 Bun 源码是 TypeScript,请在 Blob 上设置 type,或在 File 构造函数中传递 filename。

"open"

当 worker 创建完成并准备好接收消息时,会发出 "open" 事件。(此事件在浏览器中不存在。)
index.ts
Bun 会在 worker 准备好之前将消息排队,因此您无需在发送消息前等待 "open" 事件。

使用 postMessage 发送消息

要发送消息,请使用 worker.postMessage 和 self.postMessage。消息使用 HTML 结构化克隆算法 进行序列化。

性能优化

Bun 对常见数据类型的 postMessage 有快速路径: 字符串快速路径 - 当发送纯字符串时,Bun 完全绕过结构化克隆算法,因此没有序列化开销。 简单对象快速路径 - 对于仅包含原始值(字符串、数字、布尔值、null、undefined)的纯对象,Bun 直接存储属性,无需完整结构化克隆。 满足以下条件的对象会触发简单对象快速路径:
  • 是没有原型链修改的纯对象
  • 仅包含可枚举、可配置的数据属性
  • 没有索引属性或 getter/setter 方法
  • 所有属性值都是原始值或字符串
通过这些快速路径,Bun 的 postMessage 性能提升 2-241 倍,因为消息长度不再对性能产生显著影响。 Bun(带快速路径):
Node.js v24.6.0(供对比):
要接收消息,请在 worker 和主线程上使用 message 事件处理器。

终止 worker

Worker 实例在其事件循环没有剩余任务可执行时会自动终止。在全局对象或任何 MessagePort 上附加 "message" 监听器会保持事件循环运行。要强制终止 Worker,请调用 worker.terminate()。
index.ts
调用 worker.terminate() 会使 worker 尽快退出。

process.exit()

worker 可以使用 process.exit() 自行终止。这不会终止主进程。与 Node.js 一样,process.on('beforeExit', callback) 和 process.on('exit', callback) 会在 worker 线程上触发(而不是在主线程上),并且退出代码会传递给 "close" 事件。

"close"

当 worker 被标记为已终止时,会发出 "close" 事件;worker 本身可能需要一些时间才能完全退出。CloseEvent 包含传递给 process.exit() 的退出代码,如果因其他原因关闭则为 0。
index.ts
此事件在浏览器中不存在。

管理生命周期

默认情况下,活跃的 Worker 会保持主(启动)进程存活,因此像 setTimeout 和 promise 这样的异步任务会保持进程运行。附加 message 监听器也会保持 Worker 存活。

worker.unref()

要阻止正在运行的 worker 保持进程存活,请调用 worker.unref()。这会将 worker 的生命周期与主进程解耦,与 Node.js 的 worker_threads 行为一致。
index.ts
worker.unref() 在浏览器中不可用。

worker.ref()

要保持进程存活直到 Worker 终止,请调用 worker.ref()。Worker 默认是 ref 状态;ref 状态的 worker 仍然需要其事件循环上有任务(例如 "message" 监听器)才能继续运行。
index.ts
或者,您也可以向 Worker 传递一个 options 对象:
index.ts
worker.ref() 在浏览器中不可用。

使用 smol 节约内存

Bun 的 Worker 支持 smol 模式,可以在牺牲性能的情况下减少内存使用。要启用它,请在 Worker 构造函数的 options 对象中传递 smol: true。
index.ts
设置 smol: true 会将 JSC::HeapSize 设置为 Small 而不是默认的 Large。

环境数据

使用 setEnvironmentData() 和 getEnvironmentData() 在主线程和 worker 之间共享数据。
index.ts

Worker 事件

使用 process.on() 监听 worker 创建事件:
index.ts

Bun.isMainThread

检查 Bun.isMainThread 来判断您是否在主线程上。