【JS 】SharedWorker 優(yōu)化前端輪詢請求

1. 背景

目前公司系統(tǒng)首頁存在一個定時的輪詢請求/Admin/Dashboard/GetAppRelaseNotice,包含一些需要實時反映在前端的操作(如:頁面版本,站內(nèi)信,頁面配置更新等)

問題很明顯,單個頁面的情況下,每分鐘會發(fā)送一次請求;
但如果同時打開多個tab,每個tab每分鐘都會發(fā)送一次請求

2. 思路

針對這個情況,可以使用 SharedWorker + BroadcastChannel 來實現(xiàn)多個tab共用一個后臺任務(wù)的情況,減少后端服務(wù)器壓力的同時也可以提升部分前端的性能;

SharedWorker接口代表一種特定類型的 worker,可以從幾個瀏覽上下文中訪問。
BroadcastChannel接口代理了一個命名頻道。它允許同源的不同瀏覽器窗口下的不同文檔之間相互通信。

  1. 使用SharedWorker將請求任務(wù)移至后臺輪詢,多頁面共享
  2. 通過BroadcastChannel通知所有頁面請求結(jié)果
  3. 兼容不支持 SharedWorker 的瀏覽器

3. 編碼

3.1 使用SharedWorker將請求任務(wù)移至后臺輪詢,多頁面共

建立一個后臺任務(wù)js文件 GetAppRelaseNotice.js

onconnect = function (e) {
    checkAppReleaseCallBack();
    setInterval(checkAppReleaseCallBack, 1000 * 1);  //先設(shè)置1秒鐘,用于測試
}

function checkAppReleaseCallBack() {
    // 這里請求 GetAppRelaseNotice 接口獲取返回值
}

頁面啟動后臺任務(wù)

function startCheckAppRelease() {
    // 給后臺任務(wù)一個名字 GetAppRelaseNotice 后面用于調(diào)試
    const worker = new SharedWorker('/Scripts/Workers/GetAppRelaseNotice.js', "GetAppRelaseNotice");
    worker.port.start();
}

3.2 通過BroadcastChannel通知所有頁面請求結(jié)果

// 后臺任務(wù)js
const broadcast = new BroadcastChannel('LinkMore:GetAppRelaseNotice');
broadcast.postMessage(data); //發(fā)送廣播數(shù)據(jù)

// 頁面js,訂閱廣播
const broadcast = new BroadcastChannel('LinkMore:GetAppRelaseNotice');
broadcast.onmessage = (msg) => {
    const data = msg.data; // 獲取廣播數(shù)據(jù)
};

3.3 兼容不支持 SharedWorker 的瀏覽器

// 檢測應(yīng)用發(fā)版通知
function startCheckAppRelease() {
    if (typeof window.SharedWorker === "undefined") { // 如果不存在則沿用老的邏輯
        checkAppReleaseCallBack();
        setInterval(checkAppReleaseCallBack, 1000 * 60);
    } else {
        // 這里處理 SharedWorker
    }
}

4. 完整代碼

GetAppRelaseNotice.js

let timer;
onconnect = function (e) {
    checkAppReleaseCallBack();
    clearInterval(timer);
    timer = setInterval(checkAppReleaseCallBack, 1000 * 60);
}
// 創(chuàng)建廣播對象
const broadcast = new BroadcastChannel('LinkMore:GetAppRelaseNotice');
function checkAppReleaseCallBack() {
    fetch("/Admin/Dashboard/GetAppRelaseNotice", { method: "POST" })
        .then(r => r.text())
        .then(JSON.parse)
        .then(r => broadcast.postMessage(r));
}

頁面代碼


function startCheckAppRelease() {
    if (typeof window.SharedWorker === "undefined") {
        checkAppReleaseCallBack();
        setInterval(checkAppReleaseCallBack, 1000 * 60);
    } else {
        const worker = new SharedWorker('/Scripts/Workers/GetAppRelaseNotice.js', "GetAppRelaseNotice");
        worker.port.start();
        // 訂閱廣播消息
        const broadcast = new BroadcastChannel('LinkMore:GetAppRelaseNotice');
        broadcast.onmessage = msg => {
            const rst = msg.data; // 獲取廣播數(shù)據(jù)
            doAppReleaseCallBack(rst);
        };
    }
}

function checkAppReleaseCallBack() {
    $.post("/Admin/Dashboard/GetAppRelaseNotice", function (rst) {
        checkAppReleaseCallBack(rst);
    })
}

function doAppReleaseCallBack(rst) {
    // 業(yè)務(wù)邏輯不變
    if (rst.result == 0 && rst.data != "" && rst.data != null) {
        document.querySelector("#ReleaseNotice").stop();
        $("#ReleaseNotice").show();
        $("#ReleaseNotice").html(rst.data);
        document.querySelector("#ReleaseNotice").start();
    } else {
        $("#ReleaseNotice").hide();
    }
}

5. 調(diào)試

瀏覽器輸入:chrome://inspect

多個頁面都可以收到消息,但后臺任務(wù)只發(fā)一次請求

所有頁面關(guān)閉后任務(wù)會自動停止

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容