
Deno 1.36.4+ 支持通过 ReadableStream 的 cancel 方法捕获客户端主动断开连接(如关闭页面、终止请求),当连接中断时自动触发并传入 'resource closed' 原因,可用于及时停止数据生成器、释放内存或关闭关联 worker。
denon 1.36.4+ 支持通过 readablestream 的 `cancel` 方法捕获客户端主动断开连接(如关闭页面、终止请求),当连接中断时自动触发并传入 `'resource closed'` 原因,可用于及时停止数据生成器、释放内存或关闭关联 worker。
在使用 Deno.serve 实现服务端流式响应(如 SSE、大文件分块传输或实时数据推送)时,一个常见但关键的挑战是:如何感知客户端中途断连,并立即终止后端耗时的数据生产逻辑(例如异步迭代器、后台 worker 或数据库游标)? 与传统 Node.js 的可写流(res.on('close'))或 fetch 的 signal 不同,Deno.serve 的响应模型是声明式的——你只需返回一个 Response 对象,无法直接监听底层连接状态。
幸运的是,自 Deno v1.36.4 起,运行时已原生增强对流式响应中断的检测能力:当客户端断开连接(如用户关闭标签页、网络中断或调用 AbortController.abort()),底层 ReadableStream 的 cancel 方法将被自动调用,且 reason 参数精确为字符串 'resource closed'(该行为由 denoland/deno#21522 提供保障)。
因此,正确做法是在构造 ReadableStream 时显式实现 cancel 回调,并在此处执行资源清理:
Deno.serve((req) => {
// 每个请求独立创建数据源(例如从 DB 查询、调用外部 API 或启动 worker)
const asyncIterator = getChunkIterator(req.url);
const stream = new ReadableStream({
async pull(controller) {
try {
const { value, done } = await asyncIterator.next();
if (done) {
controller.close();
return;
}
controller.enqueue(value);
} catch (err) {
controller.error(err);
}
},
// ✅ 关键:处理客户端断连
async cancel(reason) {
console.log(`Stream cancelled: ${reason}`);
if (reason === "resource closed") {
// ? 立即终止数据生产者,避免僵尸任务
if (typeof asyncIterator.return === "function") {
await asyncIterator.return(); // 标准 async iterator cleanup
}
// 若使用 Deno.worker 或其他长期资源,此处应显式 terminate/close
// e.g., worker.terminate(); 或 dbConnection.close();
}
}
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive"
}
});
});⚠️ 注意事项:
- cancel 仅在 Deno ≥ 1.36.4 中可靠工作;旧版本可能不触发或返回模糊 reason(如 undefined),建议通过 Deno.version.deno 校验运行时版本。
- cancel 是异步方法,但其执行不阻塞响应结束,因此适合做非关键清理;若需强一致性(如事务回滚),应结合 AbortSignal 与 req.signal(适用于请求生命周期内可中断的 fetch/DB 操作)。
- 避免在 cancel 中执行长时间同步操作(如 while(true){}),以免延迟 V8 垃圾回收;优先使用 await + Promise.race() 设置超时。
- 若 asyncIterator 来自第三方库或自定义类,请确保其实现了 return() 方法以支持标准迭代器协议清理。
总结:借助 ReadableStream.cancel,Deno 流式服务 now 具备生产级的连接感知能力。将清理逻辑集中于此,不仅能显著降低服务器资源泄漏风险,还能提升高并发场景下的稳定性与可观测性。

















