WorkerClient
Web Worker 的请求/响应封装。原生 worker 只有「发消息」和「收消息」,并发发两个任务回来两条消息,分不清哪条对应哪个。WorkerClient 给每条请求编号,并把响应路由回它自己的 promise。
API
new WorkerClient(options)
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
create |
如何创建 worker | () => Worker |
必填 |
isProgress |
是否为进度消息(不结束请求) | (res) => boolean |
res.type === 'progress' |
getProgress |
取出进度负载 | (res) => Progress |
res.progress |
isError |
是否为错误消息 | (res) => boolean |
res.type === 'error' |
getErrorMessage |
错误文案 | (res) => string |
res.message |
timeout |
单请求超时(毫秒),只拒绝该请求 | number |
无 |
| 成员 | 说明 |
|---|---|
send(request, onProgress?, transfer?) |
发一条请求并等它的响应 |
dispose() |
终止 worker 并拒绝全部在途 |
active |
worker 是否已创建 |
pendingCount |
在途请求数 |
serveWorker(handler, options?) —— worker 侧
跑在 worker 内部的对侧件。读回每条请求的 operationId,await 你的 handler,再带着同一个 id 把结果投回去。
| 参数 | 说明 | 类型 |
|---|---|---|
handler |
(request, { progress }) => Response | Promise<Response> |
Function |
options.scope |
监听目标,默认 self;接 MessagePort 或测试替身时覆盖 |
object |
options.resultType |
handler 返回非对象时用的响应 type,默认 'result' |
string |
返回 stop 函数,用于移除监听。
示例
import { WorkerClient } from 'ranuts';
const client = new WorkerClient({
create: () => new Worker(new URL('./nlp.worker.ts', import.meta.url), { type: 'module' }),
});
await client.send({ type: 'load', modelId }, (p) => renderProgress(p.progress));
const { scores } = await client.send({ type: 'classify', lines });
client.dispose();worker 侧:
// nlp.worker.ts
import { serveWorker } from 'ranuts';
serveWorker(async (request, { progress }) => {
if (request.type === 'load') {
const device = await loadModel(request.modelId, (p) => progress(p));
return { type: 'loaded', device };
}
return { type: 'result', scores: await classify(request.lines) };
});注意
- worker 懒创建,只有第一次
send时才会创建:重活本来就不该在页面加载时就启动。 - 进度消息不结束请求,一条请求可以持续上报进度,最后只 resolve 一次。
- worker 崩溃会拒绝全部在途请求。worker 内的未捕获错误不带
operationId,无法归属到某条请求。 dispose()终止并拒绝,下次send会重建 worker。- 超时只拒绝该请求,worker 继续存活。
- 大 buffer 用
transfer转移所有权,避免结构化克隆的拷贝开销。 serveWorker连同步抛出的错误也会接住。同步 throw 会逃到 worker 的 error handler,而这条路径不带operationId,客户端只能让所有在途请求一起失败,没法只失败真正出问题的那一个。- 两端配套提供是刻意的设计。手写 worker 端的实现,正是 id 回传和错误信封的写法最容易在不同项目之间跑偏走样的地方。