SSE 事件流
SSE 使用普通 HTTP 响应持续发送文本事件。下面的服务发送三条 tick 事件后结束,便于验证分块、事件编码和取消处理。
服务代码
安装 nova-http,保存为 app.mjs 并运行 node app.mjs:
js
import { setTimeout } from "node:timers/promises";
import { createApp } from "nova-http";
export function buildApp() {
const app = createApp();
app.get("/events", async (req, res) => {
res.setHeader("content-type", "text/event-stream; charset=utf-8");
res.setHeader("cache-control", "no-cache");
await res.flushHeaders();
try {
for (let id = 1; id <= 3; id++) {
await res.write(`id: ${id}\nevent: tick\ndata: ${JSON.stringify({ id })}\n\n`);
await setTimeout(100, undefined, { signal: req.signal });
}
await res.end();
} catch (error) {
if (!req.signal.aborted) throw error;
}
});
return app;
}
if (!process.env.NOVA_DOCS_CHECK) {
await buildApp().listen(3000, "127.0.0.1");
console.log("http://127.0.0.1:3000/events");
}验证输出
sh
curl -N http://127.0.0.1:3000/events每条事件以空行结束,data 使用 JSON 序列化,避免内容中的换行破坏事件边界。浏览器可以用 EventSource 读取:
js
const events = new EventSource("http://127.0.0.1:3000/events");
events.addEventListener("tick", (event) => {
const data = JSON.parse(event.data);
console.log(data);
if (data.id === 3) events.close();
});浏览器示例假设页面与接口同源,或应用已实现适当的跨域响应。演示主动关闭 EventSource,避免有限流结束后浏览器自动重连。
改为长期事件源
将有限循环替换为业务异步迭代器,并将 req.signal 传入生产者。等待每次写入,结束时清理订阅、计时器和外部资源。心跳、Last-Event-ID 恢复策略和重试规则由应用实现,Nova 没有内置 SSE helper。