LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

還在用輪詢嗎,SSE服務(wù)端推送實(shí)現(xiàn)頁(yè)面實(shí)時(shí)更新

freeflydom
2023年6月25日 8:55 本文熱度 1907

背景

最近開發(fā)一個(gè)頁(yè)面碰到一個(gè)需求,需要對(duì)部分?jǐn)?shù)據(jù)需要實(shí)時(shí)更新狀態(tài),面對(duì)這樣子的場(chǎng)景,我們通常有以下幾個(gè)方案:

  • 輪詢,利用setTimeout定時(shí)輪詢

  • WebSocket,利用長(zhǎng)鏈接保持與服務(wù)通訊

  • SSE,服務(wù)端推送機(jī)制

是什么

我們先簡(jiǎn)單認(rèn)識(shí)一下這三者的區(qū)別:

輪詢

輪詢就是利用setTimeout的定時(shí)器,定時(shí)向服務(wù)器發(fā)起請(qǐng)求,代碼如下:

let timeout = 0;

functon rollRequest(requestFunc, times, immediately){

    if(timeout !== 0){

        clearTimeout(timeout);

    }


    if(immediately){

        requestFunc && requestFunc();

    }


    timeout = setTimeout(()=>{

        requestFunc && requestFunc();

        rollRequest(requestFunc, times, false);

    }, times);

}

缺點(diǎn)

  • 無用請(qǐng)求過多,可能每次請(qǐng)求返回的內(nèi)容都是相同

  • 實(shí)時(shí)性不可控,如果內(nèi)容更新了,但是頁(yè)面無法及時(shí)更新

WebSocket

針對(duì)上面輪詢的缺點(diǎn),WebSokcet長(zhǎng)鏈接就能很好解決,如:

  • 建立鏈接后,當(dāng)服務(wù)器發(fā)現(xiàn)數(shù)據(jù)發(fā)生變化后才返回

  • 可控性高,客戶端和服務(wù)端都可以互相通信

具體實(shí)現(xiàn)代碼如下:


// 客戶端

const ws = new WebSocket(`wss://127.0.0.1:8081`);


ws.send("這是一條消息:" + count);


// 監(jiān)聽消息

ws.onmessage = function (event) {

  console.log(event.data);

}

// 關(guān)閉連接

ws.close();


// 服務(wù)端

var WebSocketServer = require('ws').Server,

wss = new WebSocketServer({ port: 8181 });

wss.on('connection', function (ws) {

    console.log('client connected');

    ws.on('message', function (message) {

        console.log(message);

    });

});

缺點(diǎn)

可能實(shí)現(xiàn)方案對(duì)于一個(gè)頁(yè)面數(shù)據(jù)更新有點(diǎn)太重了,主要包括以下幾點(diǎn):

  • 需要有完整鏈路認(rèn)證,如:鑒權(quán)、登錄等

  • 心跳機(jī)制實(shí)現(xiàn),前后端都需要設(shè)置

  • 前后端需要規(guī)定數(shù)據(jù)返回規(guī)范

  • 服務(wù)端需要日志記錄

SSE服務(wù)端推送

SSE全稱Server-sent Events,是HTML 5 規(guī)范的一個(gè)組成部分,它主要由兩部分組成:

  • 第一部分是服務(wù)端和瀏覽器的通訊協(xié)議

  • 第二部分是前端需要利用EventSource去監(jiān)聽返回?cái)?shù)據(jù)

對(duì)比WebSocket:

SSEWebSocket
單向:僅服務(wù)端能發(fā)送消息雙向:客戶端、服務(wù)端雙向發(fā)送
僅文本數(shù)據(jù)二進(jìn)制、文本都可
常規(guī)HTTP協(xié)議WebSocket協(xié)議


實(shí)現(xiàn)一個(gè)SSE代碼如下: 

瀏覽器:


<!DOCTYPE html>

<html>

<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>SSE Demo測(cè)試</title>

</head>

<body>

    <h3>SSE返回內(nèi)容</h3>

    <div id="app"></div>

    <script>

        const eventSource = new EventSource('http://localhost:3000/sse');

        eventSource.onmessage = (event) => {

            document.getElementById('app').innerHTML = document.getElementById('app').innerHTML + `<p>${event.data}</p>`;

        }

    </script>

</body>

</html>


服務(wù)端:

const http = require('http')

const fs = require('fs')


// create a server

const server = http.createServer()


// 監(jiān)聽路由

server.on('request', (req, res) => {

    console.log('request', req.url)

    if (req.url === '/sse') {

        // Set CORS headers

        res.setHeader('Access-Control-Allow-Origin', '*')

        res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')

        res.setHeader('Access-Control-Allow-Headers', 'Content-Type')


        // Set SSE headers

        res.setHeader('Content-Type', 'text/event-stream')

        res.setHeader('Cache-Control', 'no-cache')


        // Send a ping approx every 2 seconds

        res.write("retry: 10000\n\n");

        res.write("event: connecttime\n\n");

        res.write("data: 第一次發(fā)送:" + (new Date()) + "\n");


        // 模擬收到消息推送給客戶端

        interval = setInterval(function () {

            res.write("data: 后續(xù)更新" + (new Date()) + "\n\n");

        }, 5000);

    }

    if (req.url === '/index.html' || req.url === '/') {

        // 如果是html文件,返回html文件

        res.setHeader('Content-Type', 'text/html')

        const html = fs.readFileSync('./public/index.html');

        res.end(html)

    }

})


// Listen

server.listen(3000, () => {

    console.log('Server started on port 3000')

})

缺點(diǎn)

  • 兼容性問題,但是目前絕大部分瀏覽器是支持的,如果不支持可以采用降級(jí)方案——輪詢

  • 會(huì)長(zhǎng)期占用一個(gè)http鏈接,

    • 可能會(huì)導(dǎo)致瀏覽器(chrome最大http請(qǐng)求數(shù)是6)無法發(fā)起其他請(qǐng)求,這里注意是一個(gè)坑,需要設(shè)置一個(gè)超時(shí)時(shí)間,如果長(zhǎng)時(shí)間無返回?cái)?shù)據(jù)更新可以關(guān)閉鏈接

    • 解決方案,升級(jí)到http2協(xié)議可解決http請(qǐng)求數(shù)限制問題,放到后面《如何搭建http2網(wǎng)站》講解

  • 客戶端無法主動(dòng)向服務(wù)器發(fā)起請(qǐng)求,可能造成后續(xù)問題定位難點(diǎn)

總結(jié)

前端實(shí)時(shí)更新需求,有多個(gè)解決方案,下面進(jìn)行總結(jié):

  • 目前最常用的輪詢,是最穩(wěn)定的,但是卻無法做到實(shí)時(shí)

  • WebSocket可以實(shí)時(shí),但是需要服務(wù)端和客服端長(zhǎng)期保持一致,如果哪一方斷了將無法繼續(xù)

  • SSE是服務(wù)推送,可以滿足大部分場(chǎng)景,但是也需要謹(jǐn)慎使用,避免占用過多鏈接導(dǎo)致其他無法發(fā)送請(qǐng)求

參考資料

數(shù)據(jù)不夠?qū)崟r(shí):試試長(zhǎng)連接?


原文鏈接



該文章在 2023/6/25 8:55:29 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
日本一区二区在线 | 天天在线精品视频一区二区 | 亚洲日本文字天天更新 | 在线观看国产激情免费 | 中文字幕乱在线伦视频高濑 | 亚洲AV福利无限在线观看 |