Skip to content

WorkerClient

Web Worker 的请求/响应封装。原生 worker 只有「发消息」和「收消息」,并发发两个任务回来两条消息, 分不清哪条对应哪个。WorkerClient 给每条请求编号,并把响应路由回它自己的 promise。

API

new WorkerClient(options)

参数说明类型默认值
create如何创建 worker() => Worker必填
isProgress是否为进度消息(不结束请求)(res) => booleanres.type === 'progress'
getProgress取出进度负载(res) => Progressres.progress
isError是否为错误消息(res) => booleanres.type === 'error'
getErrorMessage错误文案(res) => stringres.message
timeout单请求超时(毫秒),只拒绝该请求number
成员说明
send(request, onProgress?, transfer?)发一条请求并等它的响应
dispose()终止 worker 并拒绝全部在途
activeworker 是否已创建
pendingCount在途请求数

serveWorker(handler, options?) —— worker 侧

跑在 worker 内部的对侧件。读回每条请求的 operationId,await 你的 handler, 再带着同一个 id 把结果投回去。

参数说明类型
handler(request, { progress }) => Response | Promise<Response>Function
options.scope监听目标,默认 self;接 MessagePort 或测试替身时覆盖object
options.resultTypehandler 返回非对象时用的响应 type,默认 'result'string

返回 stop 函数,用于移除监听。

示例

js
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 侧:

js
// 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) };
});

注意

  1. worker 懒创建,首次 send 才创建 —— 重活不该在页面加载时就起。
  2. 进度消息不结束请求,一条请求可以持续上报进度,最后只 resolve 一次。
  3. worker 崩溃会拒绝全部在途请求。worker 内的未捕获错误不带 operationId,无法归属到某条请求。
  4. dispose() 终止并拒绝,下次 send 会重建 worker。
  5. 超时只拒绝该请求,worker 继续存活。
  6. 大 buffer 用 transfer 转移所有权,避免结构化克隆的拷贝开销。
  7. serveWorker 连同步抛错一起接住。sync throw 会逃到 worker 的 error handler, 而那条路径不带 operationId —— 客户端只能把所有在途请求一起失败,而不是坏掉的那一个。
  8. 两侧一起提供是刻意的。手写 worker 侧正是 id 回传与错误信封在各项目间跑偏的地方。

Released under the MIT License.