Worker 怎么感知客户端断开连接?

我用 curl -m 1 在 1 秒后主动断开连接,同一份代码、同一个兼容性日期,加了一个标志,abort 监听器触发;不加,监听器没有任何反应。

所以答案是:用 request.signal 上的 abort 事件,但要在 compatibility_flags 里显式写 enable_request_signal。 而且它只能当尽力而为的清理钩子,我在本地只复现出一种触发时机。

官方兼容性标志页没有给 enable_request_signal 标注“默认开启”的日期,所以别假设它默认就有。下面讲怎么开、什么情况下会触发,以及反方向的问题:对外调用怎么设超时。

怎么开启 request.signal?

官方兼容性标志页的条目是“Enable Request.signal for incoming requests”。开启 enable_request_signal 后,可以在 request.signal 上挂 abort 监听,在客户端取消请求时做事;关闭标志是 disable_request_signal。显式声明:

{
  "name": "demo",
  "main": "src/index.ts",
  "compatibility_date": "2026-10-01",
  "compatibility_flags": ["enable_request_signal"]
}
export default {
  async fetch(request: Request): Promise<Response> {
    request.signal.addEventListener("abort", () => console.log("client gone"));
    return new Response("ok");
  },
} satisfies ExportedHandler;

客户端断开时 abort 一定会触发吗?

不一定。我在本地(wrangler dev --local,兼容性日期 2026-10-01,curl -m 1 断开)试了两种情形:

  • 响应是流式的,返回的 Response 已经在发送:加了 enable_request_signal,客户端断开后监听器触发;不加该标志,监听器不触发。
  • handler 还在 await sleep,没有返回 Response 时客户端断开:即使加了标志,我也没有观察到 abort,signal.aborted 一直是 false,handler 照常跑完。

所以我能复现的只有“开了标志、响应已经开始发送、客户端断开”这一种。线上其他时机,比如响应返回之前,官方没有说明,我也无法在本地验证。把 request.signal 当作尽力而为的清理钩子,不要让计费或数据一致性依赖它。

客户端断开后,怎么取消上游调用?

兼容性标志页另有一个独立条目 request_signal_passthrough:设置后,进来的请求的 AbortSignal 会在你用 fetch() 转发子请求时一并传下去,反向的标志是 no_request_signal_passthrough,同样没有标注默认日期。

想让客户端断开时取消上游调用,更直白的做法是自己把 request.signal 传给下游:

fetch(url, { signal: request.signal })

对外调用怎么设超时?

平台没有替你设“请求总超时”,要自己决定等多久。对外调用用 AbortSignal.timeout:

const res = await fetch("https://api.example.com/slow", {
  signal: AbortSignal.timeout(3000),
});

这是对外设超时,request.signal 是对内感知断开,两个方向不要混。资源限额层面的上限,见 Workers 的 CPU 时间和墙钟时间有什么区别;响应之后的工作怎么跑,见 响应返回之后,Worker 里的代码还能继续跑吗。

两个标志的名称与含义来自官方兼容性标志页,我没有在线上验证,官方也没有标注默认开启的日期。上面两种断开情形的结果是我在 wrangler dev --local(wrangler 4.151.3,兼容性日期 2026-10-01)上跑出来的,线上其他触发时机我无法验证。AbortSignal.timeout 的用法我没有单独在本地测过。行为会变化,以官方文档为准。