上交所回复一次发送三到四次

问题描述 投票:0回答:1

我正在尝试在 NodeJS 服务器和 TypeScript 前端之间设置 SSE。我的服务器代码如下所示:

let sseInterval: { [index: string]: NodeJS.Timer } = {};
this.app.get('/events/:id', (req, res) => {
    const headers = {
        'Content-Type': 'text/event-stream',
        'Connection': 'keep-alive',
        'Cache-Control': 'no-cache'
    };
    res.writeHead(200, headers);

    const instanceId = req.params.id;
    const instance = this.findInstance(instanceId);

    if (!instance) {
        global.logger.debug('sse closed', {metadata: {for: instanceId}})
        clearInterval(sseInterval[instanceId]);
        res.end();
        return;
    }

    global.logger.debug('sse connected', {metadata: {for: instanceId, instance: instance.config()}})
    res.write(`data: ${JSON.stringify(instance.all())}\n\n`);

    sseInterval[instanceId] = setInterval(() => {
        global.logger.debug('sse interval', {metadata: {for: instanceId}})
        res.write(`data: ${JSON.stringify(instance.all())}\n\n`);
    }, 1000);


    req.on('close', () => {
        clearInterval(sseInterval[instanceId]);
        res.end();
    });
});

对于前端,我使用以下代码:

const datapolling = () => {
    let eventSource: EventSource = new EventSource(window.server.url + '/events/' + window.server.key);

    eventSource.onopen = (event) => {
        console.log('connected', event);
    }

    eventSource.onmessage = (event) => {
        console.log('onmessage', new Date(), event);
        const json = JSON.parse(event.data);

        updateGUI(json);

    };

    eventSource.onerror = (event) => {
        console.error('error', event);

        setTimeout(datapolling, 500);
    };

    window.addEventListener('beforeunload', () => {
        eventSource.close();
    });
}

console.log('polling', new Date());
datapolling();

问题是,前端每 3000 毫秒才接收一次事件,但一次会接收 3-4 个事件。如果我将后端间隔设置为 500 毫秒,则我每 1500 毫秒获取一次前端事件,再次一次 3-4 个。

有什么明显的我做错的事情吗?

node.js typescript server-sent-events
1个回答
0
投票

Basic implementation of SSE (server sent events)
从服务器单向发送事件:

服务器端:

this.router.get("/sse", async (req: Request, res: Response) => {
  // SSE Headers
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.flushHeaders();

  //SSE
  const sseId = new Date().toDateString();
  this.writeEvent(res, sseId, `START`);
  this.writeEvent(res, sseId, `0`);
  this.writeEvent(res, sseId, `1`);

  setTimeout(()=>{
    this.writeEvent(res, sseId, `END`);
  },2000);

  //On close event end SSE event emission
  res.on("close", () => {
    res.emit("close");
    res.end();
  });
});

前端侧:

const source = new EventSource("http://localhost:8000/api/sse");

source.onopen = () => {
  // console.log("SSE opened!");
};

source.onmessage = (e: MessageEvent) => {
  // In my case I am using alert to see data 
  // alert(e.data);

  const p = e?.data;

  //Send close event to sse open channel
  if (t == "END") {
    source.close();
  }
};

source.onerror = (e: Event) => {
  console.error("Error: ", e);
};
© www.soinside.com 2019 - 2024. All rights reserved.