Nodejs實現(xiàn)獲取實時數(shù)據(jù)的三種主流方式詳解
本文聊聊前端獲取實時數(shù)據(jù)的三種主流方式。
想象一下,我們在網(wǎng)上購物時,經(jīng)常能看到最新的優(yōu)惠信息彈出,或者在社交媒體上看到朋友的最新動態(tài)更新。這些都是因為后端在默默地向我們的頁面推送了最新的消息。那么,這背后到底使用了什么樣的技術呢?主要有三種方式:輪詢(Polling)、網(wǎng)頁套接字(WebSocket) 和服務器發(fā)送事件(Server-Sent Events, SSE)。下面,我們就來近距離接觸一下它們。
輪詢(Polling)
原理
輪詢的工作方式很像是孩子不斷地問父母“我們到了嗎?”。在這個比喻中,前端(孩子)定時向后端(父母)發(fā)送請求來檢查是否有新數(shù)據(jù)(是否到目的地了)。輪詢又分為短輪詢和長輪詢兩種。
- 短輪詢:前端每隔一定時間就發(fā)送一個請求,無論數(shù)據(jù)是否更新,后端都立即返回響應。
- 長輪詢:前端發(fā)出請求后,后端會掛起這個請求,直到有數(shù)據(jù)更新或者超時,才返回響應。
優(yōu)缺點
總體上說,輪詢的優(yōu)點在于它簡單易實現(xiàn),幾乎所有的服務器和客戶端技術都能支持。但缺點也很明顯,因為它需要不斷地發(fā)送請求,這會導致大量的網(wǎng)絡流量,而且實時性不高,數(shù)據(jù)更新有延遲。
具體到短輪詢和長輪詢,可以對它倆再做一個對比:
短輪詢
優(yōu)點: 實現(xiàn)簡單,兼容性好。
缺點: 頻繁的請求會增加服務器負擔,實時性不夠,資源浪費較多。
長輪詢
優(yōu)點: 相比短輪詢,減少了請求次數(shù),提高了實時性。
缺點: 實現(xiàn)相對復雜,服務器端需要維護掛起的請求,可能會導致資源占用。
適用場景
輪詢通常用在對實時性要求不是特別高的場景,比如一些后臺管理系統(tǒng)的消息通知、網(wǎng)頁上的非實時統(tǒng)計信息展示。下面是使用輪詢的一些真實案例:
- 微信掃碼登錄:微信的掃碼登錄功能使用的是輪詢機制。當你掃描二維碼時,你的手機上的微信客戶端會向服務器發(fā)送信息,然后你的網(wǎng)頁客戶端會周期性地詢問服務器,用戶是否已經(jīng)通過手機確認。這里使用輪詢是因為登錄操作并不頻繁,且對實時性的要求不需要毫秒級,而且輪詢是一種簡單且兼容性好的實現(xiàn)方式。
- Facebook的實時通知:在Facebook早期,他們使用長輪詢來實現(xiàn)實時通知。用戶的瀏覽器會開啟一個到服務器的長連接,這樣一旦有新通知,服務器就能立即推送數(shù)據(jù)。這種方式對于當時的技術來說是一個很好的折中方案,因為它在不犧牲太多實時性的情況下,減少了請求次數(shù)。
代碼示例
這里演示一個短輪詢。下面我們將要使用Node.js編寫一段后端程序,在這段代碼中我們提供兩個接口,一個接口用于接受輪詢、返回最新的消息,另一個接口則用于更新消息。
后端 poll-server.js 的代碼如下:
const express = require('express'); const app = express(); let message = "No new message"; // 指定public文件夾是靜態(tài)資源的目錄 app.use(express.static("public")); // 前端要輪詢訪問這個接口,這個接口會返回最新的message app.get('/poll', (req, res) => { res.send(message); message = "No new message"; }); // 在其他地方調(diào)用這個接口,更新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 則每隔幾秒鐘就發(fā)送一次請求,代碼如下:
<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>
程序啟動后,我們調(diào)用一次 /update,前端日志就會輸出:Here's a new message! ,否則就一直輸出:No new message。
網(wǎng)頁套接字(WebSocket)
原理
WebSocket是一種網(wǎng)絡通信協(xié)議,它提供了全雙工通信機制,它允許前后端建立一個持久的連接,并且雙方都可以通過這個連接隨時發(fā)送數(shù)據(jù)。就像打電話,雙方可以隨時說話和聽對方說話。
優(yōu)缺點
WebSocket 的優(yōu)點在于它能夠提供真正的實時通信,服務器和客戶端都可以隨時發(fā)送數(shù)據(jù),而且相比輪詢,它減少了HTTP請求的開銷。但缺點是它的實現(xiàn)相對復雜,在弱網(wǎng)環(huán)境下可能不穩(wěn)定,而且舊版的瀏覽器可能不支持 WebSocket。
適用場景
WebSocket 非常適合需要高實時性的場景,比如在線游戲、股票交易平臺、實時聊天應用等。下面是使用WebSocket的一些真實案例:
- Slack:這個流行的團隊溝通工具使用WebSocket來實現(xiàn)實時消息傳輸。由于團隊成員需要即時接收信息和通知,WebSocket的全雙工通信機制提供了幾乎零延遲的數(shù)據(jù)交換。
- 多人在線游戲:許多現(xiàn)代的多人在線游戲使用WebSocket來同步玩家之間的狀態(tài)。這種技術允許快速的數(shù)據(jù)傳輸,確保了游戲體驗的流暢和實時互動。
代碼示例
在Node.js中使用ws模塊來創(chuàng)建一個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!
前端會收到服務端發(fā)送的 something
服務器發(fā)送事件 (SSE)
原理
服務器發(fā)送事件(SSE)就像是一個廣播站,當有新節(jié)目(數(shù)據(jù))時,它就會向所有打開的收音機(客戶端)發(fā)送信號。SSE 允許服務器主動向客戶端發(fā)送數(shù)據(jù)流。與WebSocket不同的是,SSE 是單向通信,只能服務器向客戶端發(fā)送數(shù)據(jù)。
優(yōu)缺點
優(yōu)點:與WebSocket比,實現(xiàn)更簡單,只需要簡單的HTTP協(xié)議就可以實現(xiàn),并且支持自動重連;與輪詢比,SSE可以減少服務器和客戶端之間不必要的通信,服務器推送的方式更高效。
缺點:只支持單向通信(服務器到客戶端);注意老舊瀏覽器可能不支持SSE(比如IE6、7、8、9)。
適用場景
SSE適用于不需要客戶端向服務器發(fā)送消息的場景,比如股票價格的更新、新聞直播、或者任何只需服務器單向推送的實時數(shù)據(jù)顯示。下面是使用SSE的一些真實案例:
- ChatGPT:作為一個能夠與用戶進行互動的聊天機器人,ChatGPT使用服務器發(fā)送事件(SSE)來實現(xiàn)與用戶的實時通信。ChatGPT在響應用戶輸入時,并不需要雙向?qū)崟r通信,它主要是接收用戶的請求并返回計算結(jié)果。SSE可以在現(xiàn)有的HTTP基礎設施上運行,這對于大規(guī)模服務而言,在連接管理和服務器資源分配方面可能更容易維護和優(yōu)化。
- 股票行情更新:許多金融網(wǎng)站使用SSE來推送實時股票價格和市場數(shù)據(jù)。由于股市信息需要實時更新,SSE為用戶提供了一個不斷流動的數(shù)據(jù)源,這樣他們就可以看到最新的市場變化,而不必手動刷新頁面。
代碼示例
在Node.js中,我們可以使用如下方式創(chuàng)建一個SSE服務器,它每隔1秒向前端推送1條數(shù)據(jù):
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條數(shù)據(jù) 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>
運行效果如下:
本文簡要地介紹了三種主要的后端向前端推送數(shù)據(jù)的方式。每種技術都有自己的適用場景和優(yōu)缺點,選擇哪種技術取決于你的具體需求。不論你是在打造一個實時聊天應用,還是一個股票交易平臺,這些技術都能幫助你提供更好的用戶體驗。
以上就是Nodejs實現(xiàn)獲取實時數(shù)據(jù)的三種主流方式詳解的詳細內(nèi)容,更多關于Nodejs獲取實時數(shù)據(jù)的資料請關注腳本之家其它相關文章!
相關文章
nodejs處理圖片的幾種方法總結(jié)(使用sharp、jimp及webconvert)
這篇文章主要給大家介紹了關于nodejs處理圖片的幾種方法,文中介紹的方法分別是sharp、jimp及webconvert,在開發(fā)過程中我們有時候需要對圖片進行處理,給一個圖片添加水印、多個圖片合成為一圖片等操作,需要的朋友可以參考下2023-12-12詳解從Node.js的child_process模塊來學習父子進程之間的通信
這篇文章主要介紹了從Node.js的child_process模塊來學習父子進程之間的通信,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03輕松創(chuàng)建nodejs服務器(7):阻塞操作的實現(xiàn)
這篇文章主要介紹了輕松創(chuàng)建nodejs服務器(7):阻塞操作的實現(xiàn),本文先是組出了代碼,然后對代碼一一分析,需要的朋友可以參考下2014-12-12基于NodeJS+MongoDB+AngularJS+Bootstrap開發(fā)書店案例分析
這章的目的是為了把前面所學習的內(nèi)容整合一下,這個示例完成一個簡單圖書管理模塊,因為中間需要使用到Bootstrap這里先介紹Bootstrap2017-01-01