Documentation Index
Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
Use this file to discover all available pages before exploring further.
服务器发送事件 允许您通过单个 HTTP 响应向浏览器推送一系列文本事件。客户端通过 EventSource 来接收这些事件。
在 Bun 中,您可以通过返回一个主体为流式来源的 Response,并将 Content-Type 头设置为 text/event-stream 来实现 SSE 端点。
Bun.serve 默认会在 10 秒 后关闭空闲连接。一个安静的 SSE 流会被视为空闲,因此下面的示例调用了 server.timeout(req, 0) 来禁用此流的超时。详情请参见
idleTimeout。
使用异步生成器
在 Bun 中,new Response 直接接受一个异步生成器函数。这通常是编写 SSE 端点的最简单方法——每次 yield 会向客户端刷新一块数据,如果客户端断开连接,生成器的 finally 块会执行,从而可以清理资源。
server.tsBun.serve({
port: 3000,
routes: {
"/events": (req, server) => {
// SSE 流事件间通常比较安静。
// 默认情况下,Bun.serve 会在 10 秒无活动后关闭连接。
// 禁用该请求的空闲超时,以保持流无限期打开。
server.timeout(req, 0);
return new Response(
async function* () {
yield `data: connected at ${Date.now()}\n\n`;
// 每 5 秒发送一个 tick,直到客户端断开连接。
// 客户端断开时,生成器被返回(取消),此循环自动停止。
while (true) {
await Bun.sleep(5000);
yield `data: tick ${Date.now()}\n\n`;
}
},
{
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
},
},
);
},
},
});
使用 ReadableStream
如果您的事件来自回调——消息代理、定时器、外部推送——而不是线性的 await 流,ReadableStream 通常更合适。当客户端断开连接时,Bun 会自动调用流的 cancel() 方法,因此您可以在 start() 中设置的资源进行释放。
server.tsBun.serve({
port: 3000,
routes: {
"/events": (req, server) => {
server.timeout(req, 0);
let timer: Timer;
const stream = new ReadableStream({
start(controller) {
controller.enqueue(`data: connected at ${Date.now()}\n\n`);
timer = setInterval(() => {
controller.enqueue(`data: tick ${Date.now()}\n\n`);
}, 5000);
},
cancel() {
// 当客户端断开连接时自动调用。
clearInterval(timer);
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
},
});
},
},
});