如何在响应发送后通过请求终止Deno.serve服务?
在Deno.serve响应发送完成后优雅终止服务的方案
你的问题核心是要避免用固定超时来等待响应发送,而是要在响应确实完成发送后再终止服务。以下是更优的实现方式:
实现思路
将请求处理函数改为异步函数,在返回响应前,等待响应体的发送完成事件,确保客户端已经收到响应后,再调用AbortController.abort()终止服务。这种方式无需依赖固定超时,能精准控制服务终止时机。
修改后的代码
//example.ts //deno run --allow-net=127.0.0.1 example.ts const port = 3000; const hostname = "127.0.0.1"; const ac = new AbortController(); const signal = ac.signal; let isShuttingDown = false; const server = Deno.serve( { port, hostname, signal }, async (req: Request, _info: Deno.ServeHandlerInfo) => { if (isShuttingDown) { return new Response("Server is shutting down!", { status: 503 }); } const url = new URL(req.url); if (url.pathname === "/shutdown") { isShuttingDown = true; const response = new Response(null, { status: 202 }); // 等待响应发送完成 if (response.body) { // 针对有响应体的情况,等待流关闭 await response.body.getReader().closed; } else { // 无响应体时,用微任务确保响应已被处理 await new Promise(resolve => queueMicrotask(resolve)); } // 响应发送完成后终止服务 ac.abort(); return response; } return new Response("hello"); }, ); await server.finished; console.log("server stopped");
关键逻辑说明
- 异步处理函数:将请求 handler 声明为
async,这样可以在内部等待异步操作完成后再返回响应。 - 响应体发送完成检测:
- 如果响应包含 body(比如返回字符串、文件流等),通过
response.body.getReader().closed获取一个 Promise,它会在响应体完全发送给客户端后 resolve。 - 如果响应无 body(比如示例中的
null),通过queueMicrotask等待当前事件循环的微任务阶段完成,确保 Deno 已经处理完响应发送的逻辑。
- 如果响应包含 body(比如返回字符串、文件流等),通过
- 终止服务:在确认响应发送完成后,调用
ac.abort()即可立即终止服务,无需额外等待。
这种方式既保证了客户端能完整收到响应,又能在响应发送完成后立即停止服务,比固定超时的方式更高效、可靠。
内容的提问来源于stack exchange,提问作者c-antin
相关产品推荐
相关产品推荐

