@sv-kit/workerify
Version:
Headless Web Worker RPC: wrap(url), workerify(fn), expose(api). Abort, transferables, and typed proxies.
41 lines (40 loc) • 1.48 kB
JavaScript
// packages/workerify/src/expose.ts
/// <reference lib="webworker" />
import { collectTransferables, toPlainError } from "./transfer";
/** 在 Worker 内调用:暴露一组方法给主线程调用 */
export function expose(api) {
const controllers = new Map();
self.onmessage = async (ev) => {
const data = ev.data;
if (!data || typeof data !== "object")
return;
if (data.type === "abort") {
const c = controllers.get(data.id);
if (c)
c.abort(new DOMException("aborted", "AbortError"));
return;
}
if (data.type !== "call")
return;
const { id, method, args } = data;
const fn = api[method];
const controller = new AbortController();
controllers.set(id, controller);
const reply = (msg, transfer) => self.postMessage(msg, { transfer });
try {
if (typeof fn !== "function") {
throw new Error(`No such method: ${method}`);
}
const res = await fn(...args, { signal: controller.signal });
// 自动挑选可转移
const transfer = collectTransferables(res, 2);
reply({ type: "result", id, ok: true, value: res }, transfer);
}
catch (err) {
reply({ type: "result", id, ok: false, error: toPlainError(err) });
}
finally {
controllers.delete(id);
}
};
}