介绍
Server-Sent 事件 (SSE) 是一种用于在浏览器和服务器之间进行实时通信的技术。与 WebSockets 不同的是,SSE 建立在 HTTP 协议基础上,而不需要建立全双工的连接。SSE 可以用于实现类似在线聊天等实时通信的功能,具有轻量级、易用等特点。
在本文中,我们将介绍如何使用 SSE 实现一个简单的在线聊天应用。
实现原理
SSE 的原理很简单:浏览器通过向服务器发送一个 HTTP 请求,请求建立一个 SSE 连接。服务器接收到该请求后,将连接保持打开,并不断向浏览器发送事件消息。浏览器通过监听 EventSource
对象的 onmessage
事件,即可接收到事件消息,并进行相应的处理。
下面是一组示例代码,演示了如何在服务器使用 Node.js 和 Express 框架实现 SSE。
-- -------------------- ---- ------- -- --------- ----- ------- - ------------------ ----- --- - --------- -- -------------- --- ---- ---------------- ------------- ---- - ------------------ - --------------- -------------------- -- --------- --- -- ---------------- ----------- -- --------- ------------- ------------ -- -------- -- -- --------------- ---------------------- - ---------------- ------------------- -- ----- -- -- --- ---- ------ ----------------展开代码
上述代码实现了一个路由,用于处理客户端的 /chat
请求。该路由在响应头中设置了一些 SSE 相关的元信息,告诉浏览器这是一个 SSE 连接;然后使用 setInterval
定时向客户端发送一条消息,消息内容为当前时间戳。这个例子相当简单,只是为了演示 SSE 的基本实现原理。实际应用中,消息的内容和来源可能要复杂得多。
下面是客户端代码,使用了 EventSource
对象从服务器接收 SSE 消息。
-- -------------------- ---- ------- -- --------- ----- ----------- - --- -------------------- -- ------ --------------------------------------- --------------- - -- ------ ----------------------- --展开代码
这段代码简单明了,只需要在 EventSource
构造函数中传入 SSE 连接的 URL,然后监听 message
事件,即可接收到服务器发送的消息。在生产环境中,建议使用 WebSocket 等专业的实时通信技术代替 SSE。
实践应用
下面我们来使用 SSE 实现一个在线聊天应用。在线聊天应用的实现方式很多,本文只介绍一种基于 SSE 的实现。该实现方式支持多个用户同时聊天,用户之间的聊天消息是实时同步的。
-- -------------------- ---- ------- ---- ---------- --- --------- ----- ------ ------ ----- ---------------- ------------------- ------- --------- - ------ ----- ------- ------ ------- --- ----- ----- ----------- ------- -------------- ----- - ---------- - ------ ----- -------- ----- -------------- ----- - ---------- ----- - ---------- -- ------------- ----- - ---------- ------ - ---------- -- - -------- ------- ------ ---- ----------------------- ---- ------------------ ------ ----------- --------------- ------- ------------------------- ------ -------- ----- ------- - ----------------------------------- ----- -------- - ------------------------------------ ----- ---------- - ------------------------------- ----- ---------- - -------------------------------- --- -------- -- ------- -------- - -------------------------------- -- ----------- - -------- - ------------------- -------------------------------- --------- - -- ------ --- -- ----- ----------- - --- -------------------- -- ------ --------------------------------------- --------------- - -- ------ ----- ------- - ---------------------- -- --------- ----- ----- - ----------------------------- --------------- - ---------------- --------------- --------------------- -------------------------- -- -- ----- ------------------------------------ ---------- - ----- ------- - - ----- --------- -------- ---------------- - -------------- - ------- ------- -------- - --------------- ------------------ -- ----- ----------------------- -- ---------------- - -- -- --------- ------- -------展开代码
-- -------------------- ---- ------- -- --------- ----- ------- - ------------------ ----- --- - --------- ----- ---------- - ---------------------- -- --------- ----- ------------ - -- -- ------- --- -- ---------------- ------------- ---- - ------------------ - --------------- -------------------- ---------------- ----------- ------------- ------------ -- -- ------------- --- ---- - - -- - - -------------------- ---- - ---------------- ---------------------------------------- - -- ------------- ----- -------- - ------------------------ - ------------------------ ----- ------ - - ---- --- -------- - ---------------------------- -- -------- --------------- ---------- - --------------- - ------------------------ -- ---- --- --------- ------------------- ----------- -------------- -- -- -- ----- ----------------- ------------------ ------------- ---- - ----- ------- - -------- ------------------------------ --------------- ---------------------- -- ------------- -------------------------- -- ---------- ---------------------------------------- - ----------------------- -------------------------------- -- -------------- -- -- --- ---- ------ ---------------- ---------- - ------------------- --------- -- -- ------------- --- --------------- - --展开代码
在服务器端,我们维护了两个队列: chatMessages
和 connectionQueue
。chatMessages
保存所有聊天消息,当有新的消息时,将消息广播给所有处于连接状态的客户端;connectionQueue
保存所有的连接对象,当一个连接断开时,将该连接从队列中删除。
注意:由于 SSE 的连接是长连接,而且当前实现方式只支持单进程单线程模型。如果同时有大量的客户端连接,可能会导致服务器的资源崩溃。在生产环境中,我们需要使用专业的实时通信服务器,比如 Socket.IO、Pusher 等。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c923dfe46428fe9e030dd9