在现代的 Web 应用程序中,实现实时通讯已经成为了一项非常常见的需求。这样的需求可以通过长轮询技术来实现。在本文中,我们将探讨如何使用 Server-sent 事件在 Ruby on Rails 和小程序中构建长轮询的实时通讯系统。
什么是长轮询?
长轮询(Long Polling)是实现实时通讯的一种技术,它的原理是:客户端向服务器发送请求,服务器在没有数据可返回时,保持连接打开并持续等待,直到有新的数据可以返回。当服务器有数据可返回时,直接将数据响应给客户端,随后关闭连接。客户端在接收到数据后,可以再次发起请求重复上述过程达到实时通讯的目的。
长轮询的好处在于,与传统的轮询相比,可以减少套接字的开启和关闭次数,从而减轻服务器的负担,并提高实时性。
Server-sent 事件是什么?
Server-sent 事件(Server-sent Events)是一种 HTML5 技术,它允许服务器单向地向客户端推送数据。在使用 SSE 时,客户端通过 EventSource API 来与服务器通信,服务器通过向客户端发送 text/event-stream 类型的数据流的方式来与客户端通信。
与 WebSocket 技术相比,SSE 更加轻量级,且支持在浏览器和移动应用中使用。
实现长轮询的 Server-sent 事件流
我们首先介绍如何在 Ruby on Rails 中使用 Server-sent 事件来实现长轮询通讯。我们将假设我们已经有了一个授权用户可以查看的信息流,并且需要在新的消息到来时实时通知用户。
Rails 的控制器端点
首先,在 Rails 应用中创建一个名为“EventsController”的控制器,然后在其中创建一个名为“streams”方法的端点。代码如下:
class EventsController < ApplicationController include ActionController::Live def streams response.headers['Content-Type'] = 'text/event-stream' sse = ServerSentEvent.new(session.id) sse.on_close do sse.close end redis = Redis.new redis.subscribe('stream-message') do |on| on.message do |event, data| sse.write({ message: data }, event: 'message') end end ensure redis.quit end end
上述代码使用了 ActionController::Live 模块来打开长链接。然后它创建了一个名为‘Stream’的方法,并设置返回类型为 text/event-stream,从而与客户端建立 SSE 长链接。 SSE 的“on_close”方法用来为 SSE 结束事件提供侦听器,并且它在 SSE 连接关闭时被调用用于回收资源。
最后,订阅了 Redis 数据库的“stream-message”通道,从而在有新的消息到达时向客户端发出 SSE 通知。
客户端 JavaScript
在客户端,我们使用 EventSource API 来与“streams”方法建立 SSE 长链接,并在新数据流到来时执行特定的操作。代码如下:
let eventSource = new EventSource("/events/streams"); eventSource.onmessage = function(event) { let data = JSON.parse(event.data); if (data.event === 'message') { showMessage(data.message); } } function showMessage(message) { console.log(message); }
在上面的代码中,我们使用了“onmessage”事件来处理来自服务器的任何事件。当事件的“event”属性为“message”时,执行“showMessage”方法用于显示新的信息。
使用小程序实现 Server-sent 事件流
在小程序中,我们可以使用小程序提供的 API 直接与服务器进行 SSE 通讯,这里我们将使用 WxServerSentEventStream 封装库来简化这个过程。
import { WxServerSentEventStream } from 'wx-server-sent-event-stream'; let eventSource = new WxServerSentEventStream({ url: 'https://example.com/events/streams', logger: console, }); eventSource.addEventListener('message', (event) => { let data = JSON.parse(event.data); if (data.event === 'message') { showMessage(data.message); } }); function showMessage(message) { console.log(message); }
在上述代码中,我们使用 WxServerSentEventStream 封装来访问 SSE API。我们仅需指定 SSE URL 和日志记录器即可,与在浏览器中访问 SSE API 没有什么区别。
总结
通过本文,我们了解了如何使用 Server-sent 事件流来实现长轮询实时通讯。在 Rails 应用中,我们创建了一个名为“EventsController”的控制器,并使用 SSE 封装连接 Redis 服务器,并推送最新的流信息。在客户端上,我们使用了 HTML5 中的 EventSource API 与服务器建立 SSE 长链接。
在小程序中,我们使用 WxServerSentEventStream 封装来实现了类似的功能。
通过使用 Server-sent 事件流,我们可以实现高效的实时通讯,并减轻服务器的负载压力。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a0e74cadd4f0e0ff9162ed