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

如何在响应发送后通过请求终止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");

关键逻辑说明

  1. 异步处理函数:将请求 handler 声明为async,这样可以在内部等待异步操作完成后再返回响应。
  2. 响应体发送完成检测:
    • 如果响应包含 body(比如返回字符串、文件流等),通过response.body.getReader().closed获取一个 Promise,它会在响应体完全发送给客户端后 resolve。
    • 如果响应无 body(比如示例中的null),通过queueMicrotask等待当前事件循环的微任务阶段完成,确保 Deno 已经处理完响应发送的逻辑。
  3. 终止服务:在确认响应发送完成后,调用ac.abort()即可立即终止服务,无需额外等待。

这种方式既保证了客户端能完整收到响应,又能在响应发送完成后立即停止服务,比固定超时的方式更高效、可靠。

内容的提问来源于stack exchange,提问作者c-antin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:15:04