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 文件顶部添加此行。
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。
blob: URL 创建的 worker 支持 TypeScript、JSX 和其他文件类型。要告诉 Bun 源码是 TypeScript,请在 Blob 上设置 type,或在 File 构造函数中传递 filename。
"open"
当 worker 创建完成并准备好接收消息时,会发出 "open" 事件。(此事件在浏览器中不存在。)
index.ts
"open" 事件。
使用 postMessage 发送消息
要发送消息,请使用 worker.postMessage 和 self.postMessage。消息使用 HTML 结构化克隆算法 进行序列化。
性能优化
Bun 对常见数据类型的postMessage 有快速路径:
字符串快速路径 - 当发送纯字符串时,Bun 完全绕过结构化克隆算法,因此没有序列化开销。
简单对象快速路径 - 对于仅包含原始值(字符串、数字、布尔值、null、undefined)的纯对象,Bun 直接存储属性,无需完整结构化克隆。
满足以下条件的对象会触发简单对象快速路径:
- 是没有原型链修改的纯对象
- 仅包含可枚举、可配置的数据属性
- 没有索引属性或 getter/setter 方法
- 所有属性值都是原始值或字符串
postMessage 性能提升 2-241 倍,因为消息长度不再对性能产生显著影响。
Bun(带快速路径):
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` 模式实际上做了什么?
`smol` 模式实际上做了什么?
设置
smol: true 会将 JSC::HeapSize 设置为 Small 而不是默认的 Large。环境数据
使用setEnvironmentData() 和 getEnvironmentData() 在主线程和 worker 之间共享数据。
index.ts
Worker 事件
使用process.on() 监听 worker 创建事件:
index.ts
Bun.isMainThread
检查 Bun.isMainThread 来判断您是否在主线程上。