Channel Messaging API
Channel Messaging API允許iframe和worker通過通道與主文檔線程進行通信,通過傳遞消息。
- [引言Channel Messaging API](#引言Channel Messaging API)
- iframe的示例
- [Service Worker的示例](#Service Worker的示例)
- 瀏覽器支援
引言Channel Messaging API
在同一個文檔中運行的兩個腳本,但處於不同的上下文中,Channel Messaging API允許它們通過通道進行通信。
此用例涉及以下通信方式:
- 文檔和iframe之間的通信
- 兩個iframe之間的通信
- 兩個文檔之間的通信
它是如何工作的
調用new MessageChannel()來初始化消息通道。
1 | const channel = new MessageChannel() |
該通道具有2個屬性,稱為
- port1
- port2
這些屬性均為MessagePort對象。port1是由創建通道的一方使用的端口,而port2是通道接收器使用的端口(順帶一提,通道是雙向的,因此接收器也可以發送消息)。
在通道的每一端,您都可以在一個端口上進行侦聽,並將消息發送到另一個端口。
通過otherWindow.postMessage()方法發送消息,其中otherWindow是另一個瀏覽上下文。它接受一個消息,一個源和一個端口。
例如:
1 | const data = { name: 'Flavio' } |
消息可以是下列支援的值之一:
- 所有原始類型,但排除符號
- 數組
- 物件文本
- 字符串,日期,正則表達式對象
- Blob,File,FileList對象
- ArrayBuffer,ArrayBufferView對象
- FormData對象
- ImageData對象
- Map和Set對象
“源”是一個URI(例如https://example.org)。您可以使用'*'來允許不嚴格的檢查,或指定一個域,或者指定'/'以設置同一域目標,而無需指定所屬域。
其他瀏覽上下文使用message事件來聆聽消息:
1 | self.addEventListener('message', event => { |
self在這種情況下與使用window相同。
在事件處理程序內部,我們可以通過查看事件對象的data屬性來訪問發送的數據:
1 | self.addEventListener('message', event => { |
我們可以通過使用MessagePort.postMessage來回應:
1 | self.addEventListener('message', event => { |
通過在端口上調用close()方法,可以關閉通道:
1 | self.addEventListener('message', event => { |
iframe的示例
以下是文檔和嵌入其中的iframe之間發生的通信示例。
主文檔定義一個iframe和一個span,我們將在其中打印從iframe文檔發送的消息。一旦iframe文檔加載完畢,我們就在我們創建的channel上給它發送一個消息。
1 |
|
iframe頁面的源代碼更加簡單:
1 |
|
正如您所看到的,我們甚至不需要初始化一個channel,因為當從容器頁面接收到消息時,window.onmessage處理程序會自動運行。
發送的事件由以下屬性組成:
data:從其他窗口發送的對象origin:發送消息的窗口的源URIsource:發送消息的窗口對象
始終驗證消息發送者的來源。
e.ports[0]是我們在iframe中引用port2的方式,因為ports是一個數組,並且該端口被添加到第一個元素。
在我的回答中翻译
Service Worker的示例
Service Worker是事件驅動的worker,其是與web頁面關聯的JavaScript文件。請查看Service Workers指南以了解更多有關它們的信息。
重要的是要知道Service Worker與主線程隔離,我們必須使用消息與它們進行通信。
以下是附加到主文檔的腳本如何處理發送消息給Service Worker:
1 | // `worker`是已實例化的Service Worker |
在Service Worker代碼中,我們為message事件添加了一個事件監聽器:
1 | self.addEventListener('message', event => { |
它可以通過將消息發送到messageChannel.port2來發送消息回來:
1 | self.addEventListener('message', event => { |
瀏覽器支援
Channel Messaging API當前得到了所有主要瀏覽器的支援,其中很多瀏覽器已經支援了許多年,因此即使是舊版本的瀏覽器也支援它。有關詳細信息,請參閱https://caniuse.com/#feat=channel-messaging。