在 Web 应用程序中,通常需要将消息从服务端发送到浏览器。通常情况下,我们使用 WebSocket 或长轮询技术来实现这个功能。不过,在某些情况下,使用 WebSocket 或长轮询并不是最佳解决方案。比如说,如果我们只需要从服务端按需将消息推送到浏览器,并且不需要实时更新,则可以使用 Server-Sent Events 技术。
本篇文章将会介绍 Server-Sent Events 技术,并通过示例代码来演示如何在浏览器和服务端之间进行长时间通讯。
什么是 Server-Sent Events?
Server-Sent Events 是一种允许服务端在任意时间向浏览器推送消息的技术。与 WebSocket 不同,Server-Sent Events 不需要双向通讯,并且只支持服务端向浏览器发送消息,浏览器不会向服务端发送任何消息。
与长轮询不同,使用 Server-Sent Events 可以保持一个持久的连接,并允许服务端推送多个消息到浏览器。此外,由于 Server-Sent Events 使用纯文本协议,因此它比 WebSocket 更容易实现。
如何使用 Server-Sent Events?
Server-Sent Events 使用 EventSource
接口来实现。在浏览器端,我们可以通过创建 EventSource
对象并打开一个长连接从服务端接收消息。服务端则需要将消息发送给浏览器,并且按照规范发送特定格式的数据。
创建 EventSource 对象
要创建一个 EventSource
对象,我们需要传递一个指向服务端的 URL。可以通过以下方式创建 EventSource
对象:
const evtSource = new EventSource('/stream');
在上面的示例中,我们将创建一个 EventSource
对象,并将其链接到 /stream
URL。下面是一个例子,说明了如何在 HTML 中使用 EventSource
对象:
-- -------------------- ---- ------- --------- ----- ------ ------ ------------------ ------ --------------- ------- ------ ---- -------------------- -------- ----- ----------- - ------------------------------------ ----- --------- - --- ----------------------- ------------------- - --------------- - --------------------- -- ---------- - ----- - --------- ------- -------
在上面的示例中,我们创建了一个 EventSource
对象并将其链接到 /stream
URL。每当服务端推送一个新的消息时,将会触发 onmessage
事件,并将消息的内容添加到 messages
<div>
中。
服务端发送消息
在服务端,我们需要发送特定格式的数据,以便浏览器可以正确地解析它。每条消息需要使用 \n\n
或 \r\r
分隔符进行分隔,并加上 data:
前缀。下面是一个服务端发送 Server-Sent Events 的示例代码:
@app.route('/stream') def stream(): def event_stream(): while True: yield 'data: Hello, world!\n\n' time.sleep(1.0) return Response(event_stream(), mimetype='text/event-stream')
在上面的示例中,我们使用 Flask 框架来实现服务端。stream()
函数使用 Python 的 generator 模式来生成消息,并使用 Flask 的 Response
类来返回消息。每条消息都必须使用 \n\n
分隔符进行分隔,并使用 data:
前缀。
结论
Server-Sent Events 是一种非常有用的技术,适合那些仅仅需要将消息从服务端推送到浏览器,并且不需要实时更新的应用程序。使用 Server-Sent Events 可以保持一个持久的连接,并允许服务端推送多个消息到浏览器。由于 Server-Sent Events 使用纯文本协议,因此它比 WebSocket 更容易实现。
我们希望通过本文的介绍,能够帮助读者理解 Server-Sent Events 技术,并通过示例代码来演示如何在浏览器和服务端之间进行长时间通讯。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/66ef887c6fbf9601972fcc07