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 的用法我没有单独在本地测过。行为会变化,以官方文档为准。