@rewrite0/typed-worker
v0.0.4
Published
一个类型安全的 Web Worker 包装器,提供简洁的 API 和完整的 TypeScript 支持。
Maintainers
Readme
@rewrite0/typed-worker
一个类型安全的 Web Worker 包装器,提供简洁的 API 和完整的 TypeScript 支持。
特性
- 🔒 类型安全 - 完整的 TypeScript 类型推导和校验
- 🚀 简单易用 - 简洁直观的 API 设计
- 🔄 并发支持 - 能够正确处理并发任务,确保输入输出的一致性
- ⚡ 懒加载 - Worker 只在第一次调用时初始化
- 📦 轻量级 - 零依赖
- 🛡️ 错误处理 - 完整的错误处理
- 📤 Transferable 对象 - 支持数据所有权转移
- 🔧 优雅关闭 - 等待所有未完成任务后安全关闭 Worker,关闭期间拒绝新任务
- 📡 事件监听 - 支持监听 Worker 主动向主线程推送的事件
- 🎯 事件管理 - 完整的事件监听器管理,支持添加、移除和清理
安装
npm install @rewrite0/typed-worker或使用 pnpm:
pnpm add @rewrite0/typed-worker使用案例
1. 定义 Worker 操作
首先创建一个 worker 文件 (worker.ts):
import { defineWorkerActions, setupWorkerActions, defineWorkerSendEvent } from '@rewrite0/typed-worker';
// 定义事件类型并导出
export type Events = {
progress: [percent: number, message: string];
status: [status: 'idle' | 'working' | 'completed'];
notification: [message: string];
ping: [];
};
// 定义事件发送方法
const sender = defineWorkerSendEvent<Events>();
// 定期发送心跳事件
setInterval(() => sender('ping'), 2000);
const actions = defineWorkerActions({
async add(a: number, b: number) {
return a + b;
},
async processData(data: string) {
// 模拟重计算任务
await new Promise(resolve => setTimeout(resolve, 1000));
return data.toUpperCase();
},
async transferBuffer(buffer: ArrayBuffer) {
// 处理 ArrayBuffer
return buffer.byteLength;
},
async riskyOperation() {
throw new Error('Something went wrong');
},
async longTimeTask(duration: number) {
const sender = defineWorkerSendEvent<Events>();
// 发送开始状态
sender('status', 'working');
sender('progress', 0, '开始任务...');
// 模拟任务进度
for (let i = 0; i <= 100; i += 25) {
await new Promise(resolve => setTimeout(resolve, duration / 4));
sender('progress', i, `进度: ${i}%`);
}
sender('status', 'completed');
sender('notification', '任务完成!');
return duration;
},
});
setupWorkerActions(actions);
// 导出类型以供主线程使用
export type Actions = typeof actions;2. 在主线程中使用
import { createTypedWorker } from '@rewrite0/typed-worker';
import Worker from './worker?worker'; // Vite 风格导入
import type { Actions, Events } from './worker'; // 导入类型
// 创建类型安全的 worker 实例,支持事件监听
const worker = createTypedWorker<Actions, Events>(() => new Worker());
// 第一次调用时才会创建和初始化 Worker 实例
const result = await worker.add(1, 2); // Worker 在此时创建
// 直接调用方法 - 完整的类型推导
const result1 = await worker.add(2, 3); // number
const result2 = await worker.processData('hello'); // string
// action抛出的错误会被正常catch
try {
await worker.riskyOperation();
} catch (error) {
console.error(error.message); // "Something went wrong"
}
// 使用 call 方法进行所有权转移(Transferable)
const buffer = new ArrayBuffer(16);
console.log(buffer.byteLength) // 16
await worker.call('transferBuffer', [buffer])(buffer);
console.log(buffer.byteLength); // 0 - buffer 已被转移
// 如果不需要所有权转移,直接调用方法
const buffer2 = new ArrayBuffer(1024 * 1024);
await worker.transferBuffer(buffer2);
console.log(buffer2.byteLength); // 1048576 - buffer 仍然可用
// 正确处理多个并发任务
const tasks = Array.from({ length: 100 }, (_, i) =>
worker.add(i, 1)
);
const results = await Promise.all(tasks);
console.log(results); // [1, 2, 3, ..., 100]
// 优雅关闭 worker (会等待所有未完成任务完毕后关闭, 在关闭等待期间,任何新的任务请求都会被直接拒绝)
// 启动一些任务
const task1 = worker.longTimeTask(1000);
const task2 = worker.longTimeTask(1500);
// 开始关闭流程
const terminatePromise = worker.terminate();
// 在关闭等待期间尝试添加新任务会被拒绝
try {
await worker.add(1, 2); // 抛出错误:Worker is terminating
} catch (error) {
console.log(error.message); // "Worker is terminating, cannot accept new tasks"
}
// 正常完成任务
console.log(await task1) // 1000
console.log(await task2) // 1500
await terminatePromise // 等待关闭
console.log('ok') // ok
// 事件监听使用示例
// 监听任务进度
const unsubscribeProgress = worker.onEvent('progress', (percent, message) => {
console.log(`${percent}%: ${message}`);
});
// 监听状态变化
worker.onEvent('status', (status) => {
console.log(`状态变更: ${status}`);
});
// 监听通知消息
worker.onEvent('notification', (message) => {
console.log(`通知: ${message}`);
});
// 监听心跳事件
let heartbeatCount = 0;
const heartbeatHandler = () => {
heartbeatCount++;
console.log(`心跳 #${heartbeatCount}`);
};
worker.onEvent('ping', heartbeatHandler);
// 执行长时间任务,观察事件
await worker.longTimeTask(2000);
// 移除特定监听器
unsubscribeProgress(); // 通过返回的函数移除
worker.offEvent('ping', heartbeatHandler); // 通过 offEvent 移除
// 清除所有事件监听器
worker.clearEvents();API 参考
核心 API
createTypedWorker<Actions, Events>(setupWorker)- 创建类型安全的 Worker 实例defineWorkerActions(actions)- 定义 Worker 操作setupWorkerActions(actions)- 设置 Worker 操作defineWorkerSendEvent<Events>()- 创建事件发送函数
Worker 实例方法
call(actionName, transferableObjects?)- 调用方法并支持 Transferable 对象terminate()- 优雅关闭 WorkeronEvent(eventName, listener)- 监听事件offEvent(eventName, listener)- 移除事件监听器clearEvents(eventName?)- 清除事件监听器
