本文聊聊前端获取实时数据的三种主流方式。
想象一下,我们在网上购物时,经常能看到最新的优惠信息弹出,或者在社交媒体上看到朋友的最新动态更新。这些都是因为后端在默默地向我们的页面推送了最新的消息。那么,这背后到底使用了什么样的技术呢?主要有三种方式:轮询(polling)、网页套接字(websocket) 和服务器发送事件(server-sent events, sse)。下面,我们就来近距离接触一下它们。
轮询(polling)
原理
轮询的工作方式很像是孩子不断地问父母“我们到了吗?”。在这个比喻中,前端(孩子)定时向后端(父母)发送请求来检查是否有新数据(是否到目的地了)。轮询又分为短轮询和长轮询两种。
- 短轮询:前端每隔一定时间就发送一个请求,无论数据是否更新,后端都立即返回响应。
- 长轮询:前端发出请求后,后端会挂起这个请求,直到有数据更新或者超时,才返回响应。
优缺点
总体上说,轮询的优点在于它简单易实现,几乎所有的服务器和客户端技术都能支持。但缺点也很明显,因为它需要不断地发送请求,这会导致大量的网络流量,而且实时性不高,数据更新有延迟。
具体到短轮询和长轮询,可以对它俩再做一个对比:
短轮询
优点: 实现简单,兼容性好。
缺点: 频繁的请求会增加服务器负担,实时性不够,资源浪费较多。
长轮询
优点: 相比短轮询,减少了请求次数,提高了实时性。
缺点: 实现相对复杂,服务器端需要维护挂起的请求,可能会导致资源占用。
适用场景
轮询通常用在对实时性要求不是特别高的场景,比如一些后台管理系统的消息通知、网页上的非实时统计信息展示。下面是使用轮询的一些真实案例:
- 微信扫码登录:微信的扫码登录功能使用的是轮询机制。当你扫描二维码时,你的手机上的微信客户端会向服务器发送信息,然后你的网页客户端会周期性地询问服务器,用户是否已经通过手机确认。这里使用轮询是因为登录操作并不频繁,且对实时性的要求不需要毫秒级,而且轮询是一种简单且兼容性好的实现方式。
- facebook的实时通知:在facebook早期,他们使用长轮询来实现实时通知。用户的浏览器会开启一个到服务器的长连接,这样一旦有新通知,服务器就能立即推送数据。这种方式对于当时的技术来说是一个很好的折中方案,因为它在不牺牲太多实时性的情况下,减少了请求次数。
代码示例
这里演示一个短轮询。下面我们将要使用node.js编写一段后端程序,在这段代码中我们提供两个接口,一个接口用于接受轮询、返回最新的消息,另一个接口则用于更新消息。
后端 poll-server.js 的代码如下:
const express = require('express'); const app = express(); let message = "no new message"; // 指定public文件夹是静态资源的目录 app.use(express.static("public")); // 前端要轮询访问这个接口,这个接口会返回最新的message app.get('/poll', (req, res) => { res.send(message); message = "no new message"; }); // 在其他地方调用这个接口,更新message app.post('/update', (req, res) => { message = "here's a new message!"; res.status(200).send('message updated'); }); app.listen(3000, () => { console.log('server running on port 3000'); });
前端 poll-client.html 则每隔几秒钟就发送一次请求,代码如下:
<script type="text/javascript"> setinterval(function() { fetch('/poll') .then(response => response.text()) .then(data => { if (data !== "no new message") { console.log(data); } }); }, 5000); // 每5秒请求一次 </script>
程序启动后,我们调用一次 /update,前端日志就会输出:here's a new message! ,否则就一直输出:no new message。
网页套接字(websocket)
原理
websocket是一种网络通信协议,它提供了全双工通信机制,它允许前后端建立一个持久的连接,并且双方都可以通过这个连接随时发送数据。就像打电话,双方可以随时说话和听对方说话。
优缺点
websocket 的优点在于它能够提供真正的实时通信,服务器和客户端都可以随时发送数据,而且相比轮询,它减少了http请求的开销。但缺点是它的实现相对复杂,在弱网环境下可能不稳定,而且旧版的浏览器可能不支持 websocket。
适用场景
websocket 非常适合需要高实时性的场景,比如在线游戏、股票交易平台、实时聊天应用等。下面是使用websocket的一些真实案例:
- slack:这个流行的团队沟通工具使用websocket来实现实时消息传输。由于团队成员需要即时接收信息和通知,websocket的全双工通信机制提供了几乎零延迟的数据交换。
- 多人在线游戏:许多现代的多人在线游戏使用websocket来同步玩家之间的状态。这种技术允许快速的数据传输,确保了游戏体验的流畅和实时互动。
代码示例
在node.js中使用ws模块来创建一个websocket服务器:
const websocket = require('ws'); const wss = new websocket.server({ port: 3000 }); wss.on('connection', function connection(ws) { ws.on('message', function incoming(message) { console.log('received: %s', message); }); ws.send('something'); });
前端代码是这样的:
<script type="text/javascript"> const socket = new websocket('ws://localhost:3000'); socket.addeventlistener('open', function (event) { socket.send('hello server!'); }); socket.addeventlistener('message', function (event) { console.log('message from server ', event.data); }); </script>
运行这段程序之后,服务端会收到前端传递的 hello server!
前端会收到服务端发送的 something
服务器发送事件 (sse)
原理
服务器发送事件(sse)就像是一个广播站,当有新节目(数据)时,它就会向所有打开的收音机(客户端)发送信号。sse 允许服务器主动向客户端发送数据流。与websocket不同的是,sse 是单向通信,只能服务器向客户端发送数据。
优缺点
优点:与websocket比,实现更简单,只需要简单的http协议就可以实现,并且支持自动重连;与轮询比,sse可以减少服务器和客户端之间不必要的通信,服务器推送的方式更高效。
缺点:只支持单向通信(服务器到客户端);注意老旧浏览器可能不支持sse(比如ie6、7、8、9)。
适用场景
sse适用于不需要客户端向服务器发送消息的场景,比如股票价格的更新、新闻直播、或者任何只需服务器单向推送的实时数据显示。下面是使用sse的一些真实案例:
- chatgpt:作为一个能够与用户进行互动的聊天机器人,chatgpt使用服务器发送事件(sse)来实现与用户的实时通信。chatgpt在响应用户输入时,并不需要双向实时通信,它主要是接收用户的请求并返回计算结果。sse可以在现有的http基础设施上运行,这对于大规模服务而言,在连接管理和服务器资源分配方面可能更容易维护和优化。
- 股票行情更新:许多金融网站使用sse来推送实时股票价格和市场数据。由于股市信息需要实时更新,sse为用户提供了一个不断流动的数据源,这样他们就可以看到最新的市场变化,而不必手动刷新页面。
代码示例
在node.js中,我们可以使用如下方式创建一个sse服务器,它每隔1秒向前端推送1条数据:
const express = require('express'); const app = express(); app.use(express.static("public")); app.get('/events', function(req, res) { res.writehead(200, { 'content-type': 'text/event-stream', 'cache-control': 'no-cache', 'connection': 'keep-alive' }); // 每隔1秒钟,写出1条数据 setinterval(() => { res.write(`data: ${new date().tolocaletimestring()}\n\n`); }, 1000); }); app.listen(3000, () => { console.log('sse server running on port 3000'); });
客户端代码如下,它接收事件并打印消息:
<script type="text/javascript"> const evtsource = new eventsource('/events'); evtsource.onmessage = function(event) { console.log('new message:', event.data); }; </script>
运行效果如下:
本文简要地介绍了三种主要的后端向前端推送数据的方式。每种技术都有自己的适用场景和优缺点,选择哪种技术取决于你的具体需求。不论你是在打造一个实时聊天应用,还是一个股票交易平台,这些技术都能帮助你提供更好的用户体验。
以上就是nodejs实现获取实时数据的三种主流方式详解的详细内容,更多关于nodejs获取实时数据的资料请关注代码网其它相关文章!
发表评论