服务器发送的事件为单个客户端创建了太多的侦听器

server sent events creates way too many listeners for single client

我在 MEAN 堆栈中使用 服务器发送的事件 。 我可以在需要时将数据从服务器推送到客户端。

但是我注意到一件事,即使我是唯一访问服务器的客户端。我有 多个听众 并且广播事件说 40 个听众 如果我等待足够长的时间让客户端重新连接40 次)。

用户重新加载时也会创建多个侦听器

我如何限制听众对每个客户的每个事件说 1 个听众。对于服务器发送的事件,这甚至可能吗?

只要用户正在使用网站,我就会尝试保持 连接打开,并且仅在 browser/tab 关闭或客户端请求重新加载时关闭。

注意 : stream 是一个 EventEmitter 我用来传递事件的对象,以便可以监视所需的更改并可以通过服务器发送的事件发送适当的数据。

const function = async (request: Request, response: Response) => {
    console.log("client connected to broadcasting channel")
    console.log("listeners : " , stream.listenerCount('event-L'))
    response.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
        "X-Accel-Buffering": "no"
    });
    response.flushHeaders();

    stream.on('event-L', (event, data) => {
            console.log("Broadcasting event-L")
            response.write('event: ' + event + '\n' + 'data:' + JSON.stringify(data) + '\n\n')
        }
    })


    stream.on('event-U', (event, data) => {
            console.log("Broadcasting event-U.")
            response.write('event: ' + event + '\n' + 'data:' + JSON.stringify(data) + '\n\n')
        }

    })

    response.on('close', () => {
        console.log('client dropped me');
        response.end();
    })
}

当客户端关闭套接字时,您必须关闭为其提供服务的服务器端响应对象。

至少直接使用http包时,代码是这样的:

request.connection.on("close", function(){
  response.end();
  //Any other clean up, e.g. clearInterval() for any timers.
  console.log("Client closed connection. Aborting.");
  });

那是从我的书第 25 页复制的,Data Push Apps with HTML5 SSE。

有一个 Express.js 的例子,他们写成:

response.on('close', () => {
  console.log('client dropped me');
  //Any other clean up
  response.end();
  });

假设 request.connectionresponse 是同一个对象,那么这是相同的代码,因此根本不特定于 Express。

根据相关代码进行更新

您的 stream.on() 调用正在为事件添加侦听器。因此,当客户端断开连接时,它们是您必须做的 "clean up" 的一部分。即

response.on('close', () => {
  console.log('client dropped me');
  response.end();
  stream.off('event-L', eventLHandler);
  stream.off('event-U', eventUHandler);
  })

https://nodejs.org/api/events.html#events_emitter_off_eventname_listener

注意你需要指定事件处理函数,所以不能使用匿名函数。重构您的代码以具有两个事件处理程序(将响应作为参数)。