欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SharedWorker?多頁面相互通信示例詳解

 更新時間:2022年12月06日 09:01:04   作者:田八  
這篇文章主要為大家介紹了SharedWorker?多頁面相互通信示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

SharedWorker 是一個新的Web Worker API,它允許你在多個頁面之間共享一個Worker

SharedWorker 代表一種特定類型的Worker,可以在多個瀏覽器上下文中運行,比如多個頁面或者多個iframe。

什么是 SharedWorker

根據(jù)前幾篇的了解,大家應該對Worker有了一定的了解,SharedWorkerWorker的一種,它允許你在多個頁面之間共享一個Worker。

SharedWorker對比于Service Worker要簡單很多,同樣也是繼承與Worker,但是它的生命周期是獨立于頁面的。

SharedWorker和其他Worker的相同,都是需要同源的,它是通過url來區(qū)分是否是同一個SharedWorker。

使用 SharedWorker

SharedWorker的使用很簡單,只需要在創(chuàng)建Worker的時候,需要傳入一個name參數(shù),這個name參數(shù)就是SharedWorker的標識,相同的name會共享同一個SharedWorker。

const sharedWorker = new SharedWorker('worker.js', 'mySharedWorker');

默認情況下name并不是必須的,這個時候相同的url會共享同一個SharedWorker

const sharedWorker = new SharedWorker('worker.js');

創(chuàng)建SharedWorker之后,我們就可以通過port屬性來和SharedWorker進行通信了。

sharedWorker.port.onmessage = (e) => {
  console.log(e.data);
};

在主線程中,可以通過創(chuàng)建出來的worker對象中的port屬性來和SharedWorker進行通信。

使用worker.port.onmessage來監(jiān)聽SharedWorker的消息。

SharedWorker中,可以通過self.onconnect來監(jiān)聽SharedWorker的連接。

在監(jiān)聽事件中會獲取到與SharedWorker連接的port,通過這個port就可以和主線程進行通信了。

self.onconnect = (e) => {
  const port = e.ports[0];
  port.postMessage('hello');
};

通信還是通過postMessage來進行的。

通信

上面的通信只是一個簡單的示例,在主線程中創(chuàng)建的SharedWorker,并使用port來和SharedWorker進行通信。

通常情況下,我們會使用onmessage來監(jiān)聽SharedWorker的消息,使用這種方式默認是打開狀態(tài),如果使用addEventListener來監(jiān)聽SharedWorker的消息,需要手動調(diào)用start方法來開啟。

sharedWorker.port.addEventListener('message', (e) => {
  console.log(e.data);
});
sharedWorker.port.start();

在主線程中,我們可以通過port來實現(xiàn)和SharedWorker的通信。

// 發(fā)送消息
sharedWorker.port.postMessage('hello');
// 監(jiān)聽消息
sharedWorker.port.onmessage = (e) => {
  console.log(e.data);
};
// 或者
sharedWorker.port.addEventListener('message', (e) => {
  console.log(e.data);
});
sharedWorker.port.start();

SharedWorker中使用方式也是一樣的,不同的是,我們需要通過self.onconnect來監(jiān)聽SharedWorker的連接。

self.onconnect = (e) => {
    const port = e.ports[0];
    // 發(fā)送消息
    port.postMessage('hello');
    // 監(jiān)聽消息
    port.onmessage = (e) => {
        console.log(e.data);
    };
    // 或者
    port.addEventListener('message', (e) => {
        console.log(e.data);
    });
    port.start();
};

可以看到上面監(jiān)聽的時候,獲取port是一個數(shù)組,這是因為SharedWorker可以和多個頁面進行通信。

每個頁面都會有一個port,通過這個portSharedWorker進行通信。

通常情況下我們會記錄下所有的port,然后在需要的時候進行通信。

const ports = [];
self.onconnect = (e) => {
    const port = e.ports[0];
    ports.push(port);
    port.onmessage = (e) => {
        console.log(e.data);
    };
};
// 發(fā)送消息
function sendMessage(message) {
    ports.forEach((port) => {
        port.postMessage(message);
    });
}

上面我們的案例中,我們只創(chuàng)建了一個SharedWorker,所以只有一個port,但是如果我們創(chuàng)建了多個SharedWorker,那么就會有多個port

這里收到消息之后瀏覽器控制臺沒有任何打印信息,因為SharedWorker的作用域中沒有window對象,所以consolealert等方法都是無法使用的。

如果我們需要調(diào)試SharedWorker,可以在瀏覽器地址欄中輸入chrome://inspect/#workers,這樣就可以看到當前頁面中的SharedWorker。

指定頁面通信

上面我們拿到了所有的port,但是我們并不知道這個port是哪個頁面的,所以我們需要在創(chuàng)建SharedWorker的時候,指定每個頁面的標識。

但是很遺憾,SharedWorker并沒有提供這樣的功能,所以我們需要自己實現(xiàn)。

這里我們可以使用雙數(shù)組來實現(xiàn),一個數(shù)組用來存儲頁面的標識,一個數(shù)組用來存儲port

const pages = [];
const ports = [];
self.onconnect = (e) => {
    const port = e.ports[0];
    ports.push(port);
    // 獲取頁面標識
    const page = Math.random().toString(36).substr(2);
    port.postMessage(page);
    pages.push(page);
    // 監(jiān)聽消息
    port.onmessage = (e) => {
        const index = ports.indexOf(port);
        const page = pages[index];
        // 這樣就可以知道是哪個頁面發(fā)來的消息了
        console.log(page);
    };
};

有了上面的代碼,我們就可以知道是哪個頁面發(fā)來的消息了,并且也可以指定頁面發(fā)送消息。

實戰(zhàn)

上面我們已經(jīng)知道了如何使用SharedWorker,那么我們就可以使用它來實現(xiàn)一個簡單的聊天室。

這里我們使用SharedWorker來實現(xiàn)消息的轉(zhuǎn)發(fā),頁面之間的通信使用postMessage

  • SharedWorker
const uuids = [];
const ports = [];
self.onconnect = (e) => {
    const port = e.ports[0];
    ports.push(port);
    // 獲取頁面標識
    const uuid = Math.random().toString(36).substr(2);
    uuids.push(uuid);
    port.postMessage({
        type: 'connect',
        uuid: uuid
    });
    // 監(jiān)聽消息
    port.onmessage = (e) => {
        const index = ports.indexOf(port);
        const uuid = uuids[index];
        // 群發(fā)消息
        broadcast({
            type: 'message',
            sender: uuid,
            message: e.data.message
        });
    };
};
// 群發(fā)消息
const broadcast = (data) => {
    ports.forEach((port) => {
        port.postMessage(data);
    });
}
  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .chat {
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
        }
        #messages {
            height: 500px;
            width: 300px;
            overflow: auto;
            border: #3498db 1px solid;
            padding: 0 10px;
        }
        .chat__messages {
            flex: 1;
            overflow-y: auto;
            margin: 4px 0;
        }
        .sender {
            font-size: 12px;
            margin: 0;
            padding: 0;
        }
        .sender:after {
            content: ' :';
        }
        .message {
            width: auto;
            max-width: 300px;
            background: #3498db;
            padding: 10px;
            border-radius: 10px;
            margin: 10px 0;
            font-size: 16px;
            color: #fff;
        }
    </style>
</head>
<body>
<div class="chat">
    <div id="messages">
    </div>
    <div class="chat__input">
        <input type="text" id="message">
        <button id="send">發(fā)送</button>
    </div>
</div>
<script>
    let uuid = ''
    const sharedWorker = new SharedWorker('sharedWorker.js');
    sharedWorker.port.onmessage = (e) => {
        if (e.data.type === 'connect') {
            uuid = e.data.uuid;
            alert('連接成功')
            return;
        }
        const messageDom = `
         <div class="chat__messages">
            <p class="sender" ${uuid === e.data.sender ? 'style="color: #165DFF"' : ""}>${e.data.sender}</p>
            <p class="message">${e.data.message}</p>
         </div>
        `
        document.getElementById('messages').insertAdjacentHTML('beforeend', messageDom);
        // 滾動到底部
        document.getElementById('messages').scrollTop = document.getElementById('messages').scrollHeight;
    };
    document.getElementById('send').addEventListener('click', () => {
        const message = document.getElementById('message').value;
        if (!message) {
            alert('請輸入內(nèi)容')
            return;
        }
        const data = {
            type: 'message',
            message: message,
        }
        sharedWorker.port.postMessage(data);
        document.getElementById('message').value = '';
    });
</script>
</body>
</html>

上面的代碼我們實現(xiàn)了一個簡單的聊天室,我們可以在多個頁面打開聊天室,然后在其中一個頁面發(fā)送消息,其他頁面都會收到消息。

上面的代碼中還有一個uuid,=還可以基于這么來實現(xiàn)私聊,比如我們可以在頁面中添加一個select,然后選擇一個用戶,然后在發(fā)送消息的時候,將uuid傳遞過去,然后在SharedWorker中判斷,如果是私聊,就只發(fā)送給指定的用戶。

這一塊就留給感興趣的同學自己實現(xiàn)了。

SharedWorker 的關(guān)閉

上面我們實現(xiàn)了一個簡單的聊天室,但是我們發(fā)現(xiàn),當我們關(guān)閉頁面的時候,SharedWorker并沒有關(guān)閉,這是因為SharedWorker是一個長連接,當我們關(guān)閉頁面的時候,SharedWorker并沒有關(guān)閉,所以我們需要在頁面關(guān)閉的時候,手動關(guān)閉SharedWorker

// 關(guān)閉頁面的時候,關(guān)閉 SharedWorker
window.addEventListener('beforeunload', () => {
    sharedWorker.port.postMessage({
        type: 'close',
        uuid: uuid
    });
});
// SharedWorker.js
/** 省略其他代碼 **/
onconnect = (e) => {
    const port = e.ports[0];
    port.onmessage = (e) => {
        if (e.data.type === 'close') {
            const index = ports.indexOf(port);
            ports.splice(index, 1);
            return;
        }
    };
};

上面的代碼中,我們在頁面關(guān)閉的時候,發(fā)送一個close的消息,然后在SharedWorker中,將portports中移除,這樣就可以關(guān)閉SharedWorker了。

SharedWorker 的生命周期

SharedWorker的生命周期沒有那么復雜,不像ServiceWorker有那么多的過程,它只有一條規(guī)則,就是當所有創(chuàng)建SharedWorker的頁面關(guān)閉之后,那么SharedWorker的生命就走到了盡頭,否則它就會一直常駐。

SharedWorker 還可以做什么?

聊天室只是一個小玩具,我們還可以做很多事情,我們最常見的就是跨頁面登錄,例如GitHub,我們在一個頁面登錄,然后在其他頁面就可以獲取到登錄信息,這就是SharedWorker的一個應用場景。

還有一個應用場景就是,我們可以在一個頁面中,監(jiān)聽一個WebSocket,然后在其他頁面中,發(fā)送消息,這樣就可以實現(xiàn)跨頁面的WebSocket

其實任何跨頁面的通信,都可以使用SharedWorker來實現(xiàn),但是SharedWorker的缺點也很明顯,就是不支持IE,所以如果你的項目需要兼容IE,那么就不要使用SharedWorker了。

優(yōu)點很明確,就是可以跨頁面通信,缺點也很明顯,就是瀏覽器兼容確實有點捉急。

總結(jié)

本文主要介紹了SharedWorker的基本使用,并使用SharedWorker實現(xiàn)了一個簡單的聊天室。

SharedWorker的使用還是比較簡單的,不同于Worker那么單純,SharedWorker是一個長連接,所以我們可以在多個頁面中,共享一個SharedWorker,這樣就可以實現(xiàn)跨頁面通信了。

不同于ServiceWorker有那么多的限制,SharedWorker除了兼容性其實功能非常強大,且在實際項目中的應用場景也更加廣泛。

以上就是SharedWorker 多頁面相互通信示例詳解的詳細內(nèi)容,更多關(guān)于SharedWorker 多個頁面通信的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Layui Table js 模擬選中checkbox的例子

    Layui Table js 模擬選中checkbox的例子

    今天小編就為大家分享一篇Layui Table js 模擬選中checkbox的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • JavaScript判斷頁面加載完之后再執(zhí)行預定函數(shù)的技巧

    JavaScript判斷頁面加載完之后再執(zhí)行預定函數(shù)的技巧

    這篇文章主要介紹了JavaScript判斷頁面加載完之后再執(zhí)行預定函數(shù)的技巧,原理還是利用監(jiān)聽器監(jiān)聽元素事件、被觸發(fā)則執(zhí)行函數(shù),需要的朋友可以參考下
    2016-05-05
  • js下利用控制器載入對應腳本

    js下利用控制器載入對應腳本

    因項目開發(fā)需要,須將每一個方法都獨立成單獨的js文件以便載入、維護,所以,必須需要有一個控制器用于載入這些方法。
    2010-07-07
  • 15分鐘深入了解JS繼承分類、原理與用法

    15分鐘深入了解JS繼承分類、原理與用法

    這篇文章主要介紹了JS繼承分類、原理與用法,結(jié)合實例形式較為詳細的總結(jié)分析了javascript原型鏈繼承、構(gòu)造函數(shù)繼承、組合繼承、原型式繼承、寄生式繼承和寄生組合式繼承等相關(guān)原理及使用方法,需要的朋友可以參考下
    2019-01-01
  • 微信小程序?qū)崿F(xiàn)跳轉(zhuǎn)詳情頁面

    微信小程序?qū)崿F(xiàn)跳轉(zhuǎn)詳情頁面

    這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)跳轉(zhuǎn)詳情頁面,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 原生JavaScript實現(xiàn)Tooltip浮動提示框特效

    原生JavaScript實現(xiàn)Tooltip浮動提示框特效

    這篇文章主要為大家詳細介紹了原生JavaScript設(shè)計和實現(xiàn)Tooltip浮動提示框特效,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 純js實現(xiàn)的積木(div層)拖動功能示例

    純js實現(xiàn)的積木(div層)拖動功能示例

    這篇文章主要介紹了純js實現(xiàn)的積木(div層)拖動功能,結(jié)合實例形式分析了javascript隨機生成各種顏色div層及響應鼠標事件改變元素屬性實現(xiàn)拖動效果的相關(guān)操作技巧,需要的朋友可以參考下
    2017-07-07
  • JS向上取整、向下取整、四舍五入、取絕對值、取較大較小值及隨機數(shù)代碼示例

    JS向上取整、向下取整、四舍五入、取絕對值、取較大較小值及隨機數(shù)代碼示例

    在Js中對數(shù)值進行操作的場景有,向上取整、向下取整、四舍五入、固定精度、固定長度、取整,這篇文章主要給大家介紹了關(guān)于JS向上取整、向下取整、四舍五入、取絕對值、取較大較小值及隨機數(shù)的相關(guān)資料,需要的朋友可以參考下
    2024-04-04
  • 解析JS在獲取當前月的最后一天遇到的坑

    解析JS在獲取當前月的最后一天遇到的坑

    這篇文章主要介紹了解析JS在獲取當前月的最后一天遇到的坑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • 微信小程序?qū)崿F(xiàn)點擊空白隱藏的方法示例

    微信小程序?qū)崿F(xiàn)點擊空白隱藏的方法示例

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)點擊空白隱藏的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08

最新評論