UNPKG

fkc

Version:

FKC application service framework.

74 lines 2.55 kB
'use strict'; module.exports = (req, res) => { let heart = null; const ok = ()=>{ return req.fkc.sse; } const clean = () => { if(heart) { // 清除心跳定时器 clearInterval(heart); heart = null; } req.fkc.sse = false; req.off('close', clean); // 移除close事件监听 req.off('error', clean); // 移除error事件监听 }; const write = (data)=>{ if(!req.fkc.sse) return; try { res.write(data); } catch (e) { clean(); } }; const close = () => { clean(); try { res.end(); } catch (e) { // 忽略结束时的错误 } }; const open = (time = 30)=>{ if (req.fkc.sse) return; try { req.fkc.sse = true; res.writeHead(200, { 'Content-Type': 'text/event-stream', // 声明是SSE流 'Cache-Control': 'no-cache', // 禁止浏览器缓存,实时推送 'Connection': 'keep-alive', // 保持HTTP长连接 'X-Accel-Buffering': 'no' // 禁止nginx缓存,流式输出必备 }); time = Math.max(time, 1) * 1000; // 至少1秒 heart = setInterval(() => { // 心跳保活:30秒发送一次,防止连接超时断开(SSE规范心跳格式,浏览器不触发message事件) write(`: ping\n\n`); }, time); return true; } catch (error) { close(); return false; } } // ========== 2. 向当前客户端推送【普通消息】 ========== const send = (data) => { const sendData = typeof data === 'string' ? data : JSON.stringify(data); write(`data: ${sendData}\n\n`); // SSE标准格式:data: 内容 + 两个换行结束 }; // ========== 3. 向当前客户端推送【自定义事件消息】 ========== const sends = (eventName, data) => { const sendData = typeof data === 'string' ? data : JSON.stringify(data); write(`event: ${eventName}\ndata: ${sendData}\n\n`); }; // ========== 4. 关闭当前SSE连接 ========== req.on('close', clean); // 客户端主动断开 req.on('error', clean); // 请求异常 return { ok, open, send, sends, close }; };