useEffect(() => { const eventSource = new EventSource('/api/demo/push'); const handler = (event: MessageEvent<any>) => { let data = JSON.parse(event.data) as DemoData // 业务逻辑 ... } eventSource.addEventListener("DEMO_EVENT", handler); return () => { eventSource.removeEventListener("DEMO_EVENT", handler); } }, [])
服务端服务端的话最关键就是要把数据封装成事件流,SSE中支持的协议是GET请求,传递参数的话有些麻烦,可以传递路径参数,歪哥这里暂时不需要下面是简单示例,这里每一秒钟向客户端推送一条数据export async function GET(req: Request) { let responseStream = new TransformStream(); const writer = responseStream.writable.getWriter(); const encoder = new TextEncoder(); let eventId = 0; const intervalId = setInterval(async () => { const data = await getDataFromDB(); const eventData = JSON.stringify(data); const eventName = "DEMO_EVENT"; writer.write(encoder.encode(`event: ${eventName}\n`)); writer.write(encoder.encode(`id: ${eventId}\n`)); writer.write(encoder.encode(`data: ${eventData}\n\n`)); eventId++; if (eventId >= 3600) { clearInterval(intervalId); writer.close(); } }, 1000); return new Response(responseStream.readable, { headers: { "Content-Type": "text/event-stream", "Connection": "keep-alive", "Cache-Control": "no-cache, no-transform", }, });}
例子中有一个定时器,如果里面需要读取数据库或网络数据的话,记得加异步关键字async,然后数据流就按照SSE的数据格式,写好id、event、data就行啦最后记得设置header,主要是content-type这里面歪哥为了防止出现异常导致推送没有正确停止,设置了最长推送一个小时就关闭流,可能不需要或者有更好的方法,这个看大家实际情况了总结歪哥之前用WebSocket比较多,SSE用的少,有意思的是,最近很火的大模型对话中,AI生成回答的底层传输协议也是大量使用SSE,包括ChatGPT这种想想也是有道理,大模型回答本来就是一个个token的生成,并不是一下子把一段回复文本都放出来,天然就是这种推送的机制,SSE比较轻量,这种服务端向客户端单向推送场景使用再合适不过了,所以大家还是有必要了解一下的(图片来源网络,侵删)
0 评论