API nhắn tin kênh

API nhắn tin kênh cho phép iframe và công nhân giao tiếp với chuỗi tài liệu chính bằng cách chuyển thông báo

Giới thiệu về API nhắn tin kênh

Với hai tập lệnh chạy trong cùng một tài liệu, nhưng trong một ngữ cảnh khác, API nhắn tin kênh cho phép chúng giao tiếp bằng cách chuyển thông báo qua một kênh.

Trường hợp sử dụng này liên quan đến giao tiếp giữa

  • tài liệu và iframe
  • hai iframe
  • hai tài liệu

Làm thế nào nó hoạt động

Kêu gọinew MessageChannel()một kênh tin nhắn được khởi tạo.

const channel = new MessageChannel()

Kênh có 2 thuộc tính, được gọi là

  • port1
  • port2

Các thuộc tính đó là một đối tượng MessagePort.port1là cổng được sử dụng bởi bộ phận đã tạo kênh vàport2là cổng được sử dụng bởi bộ thu kênh (nhân tiện, kênh là hai chiều, vì vậy bộ thu cũng có thể gửi lại các tin nhắn).

Ở mỗi đầu của kênh, bạn nghe trên một cổng và bạn gửi tin nhắn đến cổng kia.

Gửi tin nhắn được thực hiện thông qua

otherWindow.postMessage()

phương pháp, ở đâuotherWindowlà bối cảnh duyệt web khác.

Nó chấp nhận một thông điệp, một nguồn gốc và cổng.

Ví dụ:

const data = { name: 'Flavio' }
const channel = new MessageChannel()
window.postMessage(data, [channel.port2])

Thông báo có thể là bất kỳ giá trị nào được hỗ trợ sau:

“Nguồn gốc” là một URI (ví dụ:https://example.org). Bạn có thể dùng'*'để cho phép kiểm tra ít nghiêm ngặt hơn hoặc chỉ định miền, hoặc chỉ định'/'để đặt mục tiêu cùng tên miền mà không cần xác định đó là tên miền nào.

Bối cảnh duyệt web khác sẽ lắng nghe thông báo bằng cách sử dụngmessagebiến cố:

self.addEventListener('message', event => {
  console.log('A new message arrived!')
})

selfcũng giống như việc sử dụngwindowtrong trường hợp này

Bên trong trình xử lý sự kiện, chúng ta có thể truy cập dữ liệu được gửi bằng cách xemdatathuộc tính của đối tượng sự kiện:

self.addEventListener('message', event => {
  console.log('A new message arrived!')
  console.log(event.data)
})

Chúng tôi có thể phản hồi lại bằng cách sử dụngMessagePort.postMessage:

self.addEventListener('message', event => {
  console.log('A new message arrived!')
  console.log(event.data)

const data = { someData: ‘hey’ } event.ports[0].postMessage(data) })

Một kênh có thể được đóng lại bằng cách gọiclose()phương thức trên cổng:.

self.addEventListener('message', event => {
  console.log('A new message arrived!')
  console.log(event.data)

const data = { someData: ‘hey’ } event.ports[0].postMessage(data) event.ports[0].close() })

Ví dụ với iframe

Đây là một ví dụ về giao tiếp xảy ra giữa tài liệu vàiframenhúng vào nó.

Tài liệu chính xác định mộtiframevà mộtspannơi chúng tôi sẽ in một tin nhắn được gửi từiframetài liệu. Ngay sau khiiframetài liệu được tải, chúng tôi gửi nó một tin nhắn trênchannelchúng tôi tạo ra.

<!DOCTYPE html>
<html>
  <body>
    <iframe src="iframe.html" width="500" height="500"></iframe>
    <span></span>
  </body>
  <script>
    const channel = new MessageChannel()
    const display = document.querySelector('span')
    const iframe = document.querySelector('iframe')
<span style="color:#a6e22e">iframe</span>.<span style="color:#a6e22e">addEventListener</span>(<span style="color:#e6db74">'load'</span>, () =&gt; {
  <span style="color:#a6e22e">iframe</span>.<span style="color:#a6e22e">contentWindow</span>.<span style="color:#a6e22e">postMessage</span>(<span style="color:#e6db74">'Hey'</span>, <span style="color:#e6db74">'*'</span>, [<span style="color:#a6e22e">channel</span>.<span style="color:#a6e22e">port2</span>])
}, <span style="color:#66d9ef">false</span>)

<span style="color:#a6e22e">channel</span>.<span style="color:#a6e22e">port1</span>.<span style="color:#a6e22e">onmessage</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">event</span> =&gt; {
  <span style="color:#a6e22e">display</span>.<span style="color:#a6e22e">innerHTML</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">data</span>
}

</script> </html>

Nguồn trang iframe thậm chí còn đơn giản hơn:

<!DOCTYPE html>
<html>
  <script>
  window.addEventListener('message', event => {
    // send a message back
    event.ports[0].postMessage('Message back from the iframe')
  }, false)
  </script>
</html>

Như bạn có thể thấy, chúng tôi thậm chí không cần khởi tạo kênh, vìwindow.onmessagetrình xử lý sẽ tự động chạy khi nhận được thông báo từ trang vùng chứa.

Sự kiện được gửi bao gồm các thuộc tính sau:

  • data: đối tượng được gửi từ cửa sổ khác
  • origin: URI gốc của cửa sổ đã gửi tin nhắn
  • source: đối tượng cửa sổ đã gửi tin nhắn

Luôn xác minh nguồn gốc của người gửi tin nhắn.

e.ports[0]là cách chúng tôi tham khảoport2trong iframe, bởi vìportslà một mảng và cổng đã được thêm vào làm phần tử đầu tiên.

Ví dụ với Nhân viên dịch vụ

Service Worker là một nhân viên hướng sự kiện, một tệp JavaScript được liên kết với trang web. Kiểm traHướng dẫn Nhân viên Dịch vụđể biết thêm về chúng.

Điều quan trọng cần biết là Service worker được tách biệt khỏi chuỗi chính và chúng tôi phải giao tiếp với họ bằng tin nhắn.

Đây là cách một tập lệnh được đính kèm với tài liệu chính sẽ xử lý việc gửi thông báo đến Service Worker:

// `worker` is the service worker already instantiated

const messageChannel = new MessageChannel()
messageChannel.port1.addEventListener('message', event => {
  console.log(event.data)
})
worker.postMessage(data, [messageChannel.port2])

Trong mã Service Worker, chúng tôi thêm một trình xử lý sự kiện chomessagebiến cố:

self.addEventListener('message', event => {
  console.log(event.data)
})

Và nó có thể gửi lại tin nhắn bằng cách đăng tin nhắn lênmessageChannel.port2, với

self.addEventListener('message', event => {
  event.ports[0].postMessage(data)
})

Hỗ trợ trình duyệt

API nhắn tin kênh hiện được hỗ trợ bởi tất cả các trình duyệt chính, nhiều trình duyệt trong số đó đã có từ lâu, vì vậy ngay cả các phiên bản cũ hơn cũng đang hỗ trợ nó. Kiểm tra tất cả các chi tiết trênhttps://caniuse.com/#feat=channel-messaging.

Tải xuống miễn phí của tôiSổ tay dành cho Người mới bắt đầu JavaScript


Các hướng dẫn khác về trình duyệt: