You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Deno中如何检测Web Worker关闭并实现错误捕获与重启?

Deno Worker 进程关闭处理与错误重启方案

核心问题说明

Deno Worker API 完全对齐浏览器 Web Worker 规范,不存在onclose事件,原生仅提供onerror监听 Worker 内的未捕获错误。默认情况下,Worker 抛出未捕获错误会导致宿主进程崩溃(配合--watch参数时,这种崩溃会触发宿主自动重启)。

可行实现方案

1. Worker 内部主动捕获错误并通知宿主

在 Worker 全局作用域捕获所有错误,阻止默认崩溃行为,通过postMessage向宿主发送退出信号:

// Worker 侧代码
globalThis.addEventListener("error", (event) => {
  // 阻止错误向上冒泡引发宿主进程崩溃
  event.preventDefault();
  // 向宿主传递错误信息与退出指令
  globalThis.postMessage({
    command: "exit",
    error: {
      message: event.message,
      filename: event.filename,
      lineno: event.lineno
    }
  });
});

// 若Worker因业务逻辑需要正常退出,也可主动发送exit指令
// globalThis.postMessage({ command: "exit" });

2. 宿主侧监听消息并处理终止与重启

在宿主进程中监听 Worker 消息,收到exit指令后主动终止 Worker,根据错误状态决定是否重启:

// 宿主侧代码
function createWorker() {
  const worker = new Worker(new URL("./worker.ts", import.meta.url).href, {
    type: "module"
  });

  worker.onmessage = (event) => {
    const { command, error } = event.data;
    if (command === "exit") {
      // 主动终止Worker实例
      worker.terminate();
      console.log("Worker已终止");

      // 存在错误时延迟重启Worker
      if (error) {
        console.error("Worker错误详情:", error);
        setTimeout(() => {
          console.log("启动Worker重启...");
          createWorker();
        }, 5000);
      }
    }
  };

  // 监听Worker初始化阶段的加载错误
  worker.onerror = (error) => {
    console.error("Worker初始化失败:", error);
    worker.terminate();
    setTimeout(() => createWorker(), 5000);
  };

  return worker;
}

// 启动首个Worker
createWorker();

--watch参数的特殊坑点

使用deno run --watch时,Worker 内的未捕获错误会触发宿主进程的热重启(这是--watch的默认机制),导致错误捕获逻辑无法正常测试。测试阶段建议暂时移除--watch参数,或确保 Worker 内所有错误都被捕获并发送exit指令,避免触发--watch的重启行为。

边界情况补充处理

若 Worker 因系统级原因(如内存不足、被外部进程强制终止)意外退出,宿主无法收到exit消息,会进入 Worker 失联状态。可通过心跳机制补充检测:

// Worker侧添加心跳发送逻辑
setInterval(() => {
  globalThis.postMessage({ command: "heartbeat" });
}, 2000);

// 宿主侧处理心跳超时
function createWorker() {
  const worker = new Worker(/* ... */);
  let heartbeatTimer: number;

  const resetHeartbeat = () => {
    clearTimeout(heartbeatTimer);
    heartbeatTimer = setTimeout(() => {
      console.log("Worker心跳超时,强制重启");
      worker.terminate();
      createWorker();
    }, 5000);
  };

  worker.onmessage = (event) => {
    if (event.data.command === "heartbeat") {
      resetHeartbeat();
    } else if (event.data.command === "exit") {
      clearTimeout(heartbeatTimer);
      // 执行原有的exit处理逻辑
      // ...
    }
  };

  resetHeartbeat();
  // ...
}

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 22:20:22