SvelteKit服务器load函数中如何返回流式响应?
在SvelteKit服务端返回实时行情流式响应的实现方案
要在SvelteKit的+page.server.js中返回流式响应,你不能在load函数里返回普通数据对象,而是要直接返回一个Response实例,同时结合ReadableStream处理实时行情推送,还要注意清理订阅避免内存泄漏。
核心实现要点
- SvelteKit的服务端
load函数支持直接返回Response对象,这是实现流式响应的关键。 - 必须在响应流关闭时取消YahooFinanceTicker的订阅,防止无效资源占用。
- 推荐使用
text/event-stream类型的响应头(Server-Sent Events,SSE),更适配实时更新场景,客户端也更容易处理。
修正后的完整代码
import YahooFinanceTicker from "yahoo-finance-ticker"; export async function load({ request }) { const ticker = new YahooFinanceTicker(); const tickerListener = await ticker.subscribe(["BTC-USD"]); const stream = new ReadableStream({ start(controller) { // 处理行情更新事件 const handleTicker = (data) => { // 用SSE标准格式封装数据,方便客户端解析 controller.enqueue(`data: ${JSON.stringify({ price: data.price })}\n\n`); }; tickerListener.on("ticker", handleTicker); // 客户端断开连接时,清理订阅并关闭流 request.signal.addEventListener("abort", () => { tickerListener.off("ticker", handleTicker); ticker.unsubscribe(["BTC-USD"]); controller.close(); }); }, // 流被主动取消时的兜底清理逻辑 cancel() { ticker.unsubscribe(["BTC-USD"]); } }); // 返回流式响应,配置适配SSE的响应头 return new Response(stream, { headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", "Connection": "keep-alive" } }); }
代码细节说明
- 订阅逻辑移入load函数:避免模块级别的订阅被多个请求共享,每个请求创建独立的ticker实例和订阅,保证数据隔离。
- SSE格式封装:通过
data: ...\n\n的格式输出数据,客户端可以用EventSourceAPI直接监听,无需手动处理流解析。 - 资源清理机制:监听请求的
abort事件(客户端关闭页面或断开连接时触发),及时取消ticker订阅并关闭流,防止内存泄漏。 - 响应头配置:设置
text/event-stream类型、禁用缓存、保持长连接,确保实时推送的稳定性。
客户端接收示例(+page.svelte)
如果需要在页面中展示实时行情,可以用EventSource实现:
<script> import { onMount } from 'svelte'; let currentPrice = "加载中..."; const eventSource = new EventSource("/"); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); currentPrice = data.price; }; // 页面卸载时关闭连接,避免无效请求 onMount(() => { return () => eventSource.close(); }); </script> <h1>BTC-USD 当前价格: {currentPrice}</h1>
内容的提问来源于stack exchange,提问作者voscausa
相关产品推荐
相关产品推荐

