PWA(Progressive Web App)入门系列:消息通讯
前言
serviceWorker 的能力決定它要處理的事情,網(wǎng)站頁面的部分邏輯處理會轉(zhuǎn)移到 serviceWorker 層進(jìn)行處理,這里就要頁面層和 serviceWorker 層進(jìn)行交互來實(shí)現(xiàn)消息通訊。
下面就說一下兩個(gè)環(huán)境下的消息通訊。
窗口向 serviceWorker 通訊
這里列舉出窗口層到 serviceWorker 層的通訊方法。
1. ServiceWorker.postMessage
頁面層可以通過 ServiceWorker 接口的 postMessage 來實(shí)現(xiàn)頁面到 serviceWorker 環(huán)境的通訊。
ServiceWorker 接口的獲取:
ServiceWorker 接口獲取有兩種方式
- navigator.serviceWorker.controller,常用這種方式。
- navigator.serviceWorker.ready.then(swReg => swReg[state]):state 為 {installing, waiting, active} 。
當(dāng) postMessage 后,serviceWorker 環(huán)境采用 onmessage 事件進(jìn)行處理。
發(fā)送消息:
發(fā)送消息實(shí)現(xiàn):
index.html
// 頁面 window 環(huán)境if(navigator.serviceWorker.controller) { // 需要判斷是否受控navigator.serviceWorker.controller.postMessage('消息'); // postMessage 的第一個(gè)參數(shù)可以是由結(jié)構(gòu)化克隆算法處理的任何值或JavaScript對象,也包括循環(huán)引用。 } 復(fù)制代碼sw.js
// serviceWorker 環(huán)境self.addEventListener("message", e => {console.log("message", e);// 從 e.data 里面取 postMessage 過來的數(shù)據(jù) }) 復(fù)制代碼接收消息:
頁面層 window 環(huán)境下接收消息需要在 ServiceWorkerContainer 接口上監(jiān)聽 onmessage:
navigator.serviceWorker.onmessage 復(fù)制代碼serviceWorker 層做定向 Client 的獲取有以下方式:
// 1. 通過 e.source.id 來定向發(fā)送消息self.addEventListener("message", e => {const client = await self.clients.get(e.source.id);client.postMessage('發(fā)給頁面層的消息'); })// 2. 直接 e.source 來定向發(fā)送消息self.addEventListener("message", e => {e.source.postMessage('發(fā)給頁面層的消息'); }) 復(fù)制代碼2. ServiceWorkerRegistration.sync.register
第二種方式,是使用 sync 的方式來實(shí)現(xiàn)頁面層到 serviceWorker 層的通訊。
這種通訊的弊端是單向的,且不可控。
但優(yōu)勢也很明顯,對于后臺同步十分有用,一旦注冊 sync 在 online 的狀態(tài)下會立即觸發(fā) serviceWorker 環(huán)境下的 onsync 事件,serviceWorker 可根據(jù)具體邏輯處理,直到 e.waitUntil 返回 Promise.resolve() 才會完成 sync,并把 sync 的 tag 清除,否則會一直按照某個(gè)周期執(zhí)行,知道 e.lastChance == true。
// 頁面層環(huán)境navigator.serviceWorker.ready.then(swReg => {swReg.sync.register('同步tag') }) 復(fù)制代碼// serviceWorker 層環(huán)境self.addEventListener("sync", e => {if(e.tag == '同步tag') {e.waitUntil(new Promise((res, rej) => {// 邏輯處理 ...return res();}))} }) 復(fù)制代碼3. MessageChannel
MessageChannel 是一個(gè)點(diǎn)對點(diǎn)的消息通道,可以很方便的實(shí)現(xiàn)消息的雙向通訊。
構(gòu)造函數(shù):
構(gòu)造函數(shù)很簡單,不需要任何參數(shù)
var channel = new MessageChannel(); 復(fù)制代碼屬性:
- MessageChannel.port1
- MessageChannel.port2
屬性中的兩個(gè) port 為 MessagePort 接口實(shí)現(xiàn),具備以下方法:
- postMessage
- start
- close
具備事件監(jiān)聽:MessagePort.onmessage。
這里發(fā)消息時(shí),主要以環(huán)境下的 postMessage 配合使用。
// 頁面層環(huán)境if(navigator.serviceWorker.controller) {var c = new MessageChannel();c.port1.onmessage = e => {// 收到傳給 port1 的消息}// 向 port2 發(fā)送消息navigator.serviceWorker.controller.postMessage('消息', [c.port2]) } 復(fù)制代碼// serviceWorker 層self.addEventListener("message", e => {// 從 e.ports 里取 MessagePorte.ports[0] && e.ports[0].postMessage('向port1發(fā)送消息') }) 復(fù)制代碼注意:MessageChannel 創(chuàng)建的通道會受 serviceWorker 的 stopWorker 影響,導(dǎo)致 MessageChannel 通道 close,也就是表現(xiàn)為通道只能用一次。所以使用 MessageChannel 通訊時(shí),每次都要?jiǎng)?chuàng)建新的通道。
serviceWorker 向窗口通訊
上面說的是窗口頁面層向 serviceWorker 環(huán)境的通訊,同樣 serviceWorker 環(huán)境層也需要向頁面層通訊。
在 serviceWorker 環(huán)境下主要有兩種向頁面層通訊的方式。
1. BroadcastChannel
第一種是 BroadcastChannel,也就是廣播信道通訊。
構(gòu)造函數(shù):
構(gòu)造函數(shù)很簡單,channel 參數(shù)為一個(gè)字符串。
var channel = new BroadcastChannel(channel); 復(fù)制代碼屬性:
- BroadcastChannel.name:構(gòu)造時(shí)的信道名。
事件:
- onmessage
- onmessageerror
方法:
- postMessage()
- close()
2. client.postMessage
第二種就是獲取相應(yīng)的 client 進(jìn)行 postMessage。
如果從 onmessage 中,是可以獲取到相應(yīng)的 sorce client 的,從而進(jìn)行雙向通訊。但在自發(fā)情況下,只能對所有 client 進(jìn)行廣播通訊。
// serviceWorker 環(huán)境clients.matchAll({type: "window" }) .then(windows => {for (const win of windows) {win.postMessage('發(fā)送消息到頁面');} }); 復(fù)制代碼博客名稱:王樂平博客
CSDN博客地址:blog.csdn.net/lecepin
本作品采用知識共享署名-非商業(yè)性使用-禁止演繹 4.0 國際許可協(xié)議進(jìn)行許可。轉(zhuǎn)載于:https://juejin.im/post/5d067f22e51d457778117390
總結(jié)
以上是生活随笔為你收集整理的PWA(Progressive Web App)入门系列:消息通讯的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS进阶(7)—— 内联元素的掌管者l
- 下一篇: haproxy对mysql集群进行负载均