Server-Sent Events(SSE)是一种用于在 Web 浏览器和服务器之间实现实时通信的技术。它允许服务器向客户端推送事件,而无需客户端发起请求。在前端开发中,SSE 可以用于实现实时通知、聊天应用、股票行情等实时数据的展示。
在实际应用中,我们可能需要同时订阅多个主题的 SSE 事件,例如同时订阅股票行情和天气预报的 SSE 事件。本文将介绍如何使用 JavaScript 实现 SSE 的多主题订阅功能。
实现多主题订阅
SSE 的基本实现非常简单,只需要使用 EventSource
对象即可。例如,下面的代码可以订阅名为 myEvent
的 SSE 事件:
const eventSource = new EventSource('/sse'); eventSource.addEventListener('myEvent', function(event) { console.log(event.data); });
但是,如果我们需要订阅多个主题的 SSE 事件,该怎么办呢?一种常见的做法是为每个主题创建一个 EventSource
对象,例如:
// javascriptcn.com 代码示例 const eventSource1 = new EventSource('/sse?topic=topic1'); eventSource1.addEventListener('myEvent', function(event) { console.log('topic1: ' + event.data); }); const eventSource2 = new EventSource('/sse?topic=topic2'); eventSource2.addEventListener('myEvent', function(event) { console.log('topic2: ' + event.data); });
这种方式虽然可行,但是有一个缺点:每个 EventSource
对象都需要创建一个新的连接。如果我们需要订阅的主题数量很多,就会导致服务器压力增大,同时也会影响客户端的性能和用户体验。
为了解决这个问题,我们可以使用一个 EventSource
对象订阅多个主题的 SSE 事件。具体来说,我们可以在服务器端将多个主题的 SSE 事件合并成一个 SSE 流,然后在客户端使用一个 EventSource
对象订阅该 SSE 流。例如,下面的代码可以订阅名为 topic1
和 topic2
的 SSE 事件:
const eventSource = new EventSource('/sse?topics=topic1,topic2'); eventSource.addEventListener('myEvent', function(event) { const data = JSON.parse(event.data); console.log(data.topic + ': ' + data.message); });
在服务器端,我们需要将多个主题的 SSE 事件合并成一个 SSE 流。具体来说,我们可以使用 Node.js 中的 EventEmitter
对象来实现。例如,下面的代码可以将名为 topic1
和 topic2
的 SSE 事件合并成一个 SSE 流:
// javascriptcn.com 代码示例 const EventEmitter = require('events').EventEmitter; const express = require('express'); const app = express(); const eventEmitter = new EventEmitter(); app.get('/sse', function(req, res) { const topics = req.query.topics.split(','); const eventSource = new EventSource('data:,'); eventSource.onopen = function() { topics.forEach(function(topic) { eventEmitter.on(topic, onEvent); }); }; eventSource.onerror = function() { topics.forEach(function(topic) { eventEmitter.removeListener(topic, onEvent); }); }; function onEvent(data) { eventSource.dispatchEvent(new Event('myEvent', { data: JSON.stringify({ topic: this.event, message: data }) })); } res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); eventSource.on('close', function() { res.end(); }); eventSource.pipe(res); }); eventEmitter.emit('topic1', 'hello'); eventEmitter.emit('topic2', 'world'); app.listen(3000);
在上面的代码中,我们首先使用 EventEmitter
对象创建了一个事件发射器 eventEmitter
,然后在路由处理函数中创建了一个 EventSource
对象。在 onopen
回调函数中,我们为每个主题注册了一个事件监听器 onEvent
,并在 onerror
回调函数中移除了这些事件监听器。在 onEvent
回调函数中,我们使用 eventSource.dispatchEvent
方法向客户端发送名为 myEvent
的 SSE 事件,并将主题和消息内容以 JSON 格式存储在 data
属性中。
最后,我们使用 eventSource.pipe(res)
方法将 SSE 流发送给客户端。在客户端,我们可以使用 EventSource
对象订阅该 SSE 流,并在 myEvent
事件的回调函数中处理 SSE 事件。在上面的代码中,我们使用 JSON.parse
方法将 data
属性解析为 JSON 对象,然后输出主题和消息内容。
总结
本文介绍了如何使用 JavaScript 实现 SSE 的多主题订阅功能。通过在服务器端将多个主题的 SSE 事件合并成一个 SSE 流,我们可以避免创建多个连接,从而减轻服务器负担,提高客户端性能和用户体验。同时,本文还介绍了如何使用 Node.js 中的 EventEmitter
对象实现 SSE 事件的合并和转发。希望本文能够帮助读者更好地理解 SSE 技术,并在实际项目中得到应用。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/66038e26d10417a222ffc019