EventSource 处理 text/event-stream 服务端推送

643 阅读1分钟

demo 示例

GIF 2024-5-16 0-38-48.gif

demo 思路

  1. 监听端口启动服务端,处理不同的请求路径,sse 路径设置相关的响应头。
  2. 客户端创建 EventSource 对象,传入服务端的服务端推送请求路径。
  3. 接受到结束消息(这里取空消息为结束标识)时,调用 close 关闭连接。

服务端相关操作

  1. 使用 node 搭建服务器(基本的服务创建套路)
import http from "http";

const port = 3006;

const server = http.createServer((request, response) => {
  response.setHeader("Access-Control-Allow-Origin", "*");
  routerHandle(request.url || "/", response);
});
  1. 路由处理函数
const routerHandle = (
  url: string,
  response: http.ServerResponse<http.IncomingMessage>
) => {
  switch (url) {
    case "/":
      break;
    case "/sse":
      response.writeHead(200, {
        connection: "keep-alive",
        "cache-control": "no-cache",
        "content-type": "text/event-stream",
      });

      recursiveGenString(15, response);
      break;
    default:
      break;
  }
};
  1. sse 响应延迟以及内容 mock
const LOREM_STRING = "这是一段测试字符串";

const generateWord = (): string => {
  const randomWordsCount = parseInt(
    String(Math.random() * LOREM_STRING.length)
  );
  const word = LOREM_STRING.slice(0, randomWordsCount);
  return word;
};

const recursiveGenString = (
  maxTimes: number,
  response: http.ServerResponse<http.IncomingMessage>
) => {
  let count = 0;
  const get = () => {
    return new Promise((resolve, reject) => {
      const responseTime = parseInt(String(Math.random() * 3)) * 1000;
      setTimeout(() => {
        const responseContent = generateWord();
        // 模拟结束
        if (count++ >= maxTimes) {
          response.end(`data:\n\n`);
          return;
        } else {
          response.write(`data: ${responseContent || "。"}\n\n`);
          resolve(1);
        }
      }, responseTime);
    }).then(() => {
      get();
    });
  };
  get();
};

客户端相关操作

  1. 创建 EventSource 对象
const eventSource = new EventSource("http://127.0.0.1:3006/sse");
  1. 处理消息
eventSource.onmessage = (e) => {
        console.log(">>", e);
        if (!e.data) {
          eventSource.close();
          return;
        }
        sseContainer.innerHTML += `${e.data}`;
      };

完整代码

ProgrammeLab/event-source-demo: client EventSource & server SSE demo (github.com)

参考

  1. EventSource - Web API | MDN (mozilla.org)