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 代码中使用 importexport 语法。与浏览器不同,您不需要传递 {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.postMessageself.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 来判断您是否在主线程上。