BroadcastChannel API memungkinkan skrip dengan origin yang sama mengirim pesan ke konteks penjelajahan lainnya. Pub/Sub dapat dianggap sebagai bus pesan sederhana yang memungkinkan semantik pub/sub antara jendela/tab, iframe, pekerja web, dan pekerja layanan.
Dasar-dasar API
Broadcast Channel API adalah API sederhana yang memudahkan komunikasi antar-konteks penjelajahan. Artinya, berkomunikasi antara jendela/tab, iframe, pekerja web, dan pekerja layanan. Pesan yang diposting ke saluran tertentu akan dikirim ke semua pemroses saluran tersebut.
Konstruktor BroadcastChannel
menggunakan satu parameter: nama saluran.
Nama tersebut mengidentifikasi channel dan ditampilkan di seluruh konteks penjelajahan.
// Connect to the channel named "my_bus".
const channel = new BroadcastChannel('my_bus');
// Send a message on "my_bus".
channel.postMessage('This is a test message.');
// Listen for messages on "my_bus".
channel.onmessage = function(e) {
console.log('Received', e.data);
};
// Close the channel when you're done.
channel.close();
Mengirim pesan
Pesan dapat berupa string atau apa pun yang didukung oleh algoritma clone terstruktur (String, Objek, Array, Blob, ArrayBuffer, Peta).
Contoh - mengirim Blob atau File
channel.postMessage(new Blob(['foo', 'bar'], {type: 'plain/text'}));
Saluran tidak akan menyiarkan ke saluran itu sendiri. Jadi, jika Anda memiliki pemroses onmessage
di halaman yang sama dengan postMessage()
ke saluran yang sama, peristiwa message
tersebut
tidak akan diaktifkan.
Perbedaan dengan teknik lain
Pada tahap ini, Anda mungkin bertanya-tanya bagaimana hal ini terkait dengan teknik lain untuk penerusan pesan seperti WebSocket, SharedWorker, MessageChannel
API, dan window.postMessage()
. Broadcast Channel API tidak menggantikan API ini. Masing-masing memiliki tujuan. Broadcast Channel API dimaksudkan untuk komunikasi one-to-many yang mudah antara skrip di origin yang sama.
Beberapa kasus penggunaan untuk saluran siaran:
- Mendeteksi tindakan pengguna di tab lain
- Mengetahui kapan pengguna login ke akun di jendela/tab lain.
- Memberi petunjuk kepada pekerja untuk melakukan beberapa tugas latar belakang
- Mengetahui kapan layanan selesai melakukan beberapa tindakan.
- Saat pengguna mengupload foto di satu jendela, teruskan foto tersebut ke halaman terbuka lainnya.
Contoh - halaman yang mengetahui kapan pengguna logout, bahkan dari tab lain yang terbuka di situs yang sama:
<button id="logout">Logout</button>
<script>
function doLogout() {
// update the UI login state for this page.
}
const authChannel = new BroadcastChannel('auth');
const button = document.querySelector('#logout');
button.addEventListener('click', e => {
// A channel won't broadcast to itself so we invoke doLogout()
// manually on this page.
doLogout();
authChannel.postMessage({cmd: 'logout', user: 'Eric Bidelman'});
});
authChannel.onmessage = function(e) {
if (e.data.cmd === 'logout') {
doLogout();
}
};
</script>
Dalam contoh lain, misalnya Anda ingin menginstruksikan pekerja layanan untuk menghapus
konten yang di-cache setelah pengguna mengubah "setelan penyimpanan offline" di aplikasi Anda.
Anda dapat menghapus cache-nya menggunakan window.caches
, tetapi pekerja layanan mungkin
sudah berisi utilitas untuk melakukannya. Kita dapat menggunakan Broadcast Channel API untuk
menggunakan kembali kode tersebut. Tanpa Broadcast Channel API, Anda harus melakukan loop pada hasil self.clients.matchAll()
dan memanggil postMessage()
di setiap klien untuk mencapai komunikasi dari pekerja layanan ke semua kliennya (kode sebenarnya yang melakukannya). Menggunakan Saluran Siaran akan membuat O(1)
ini, bukan O(N)
.
Contoh - menginstruksikan pekerja layanan untuk menghapus cache, menggunakan kembali metode utilitas internalnya.
Di index.html
const channel = new BroadcastChannel('app-channel');
channel.onmessage = function(e) {
if (e.data.action === 'clearcache') {
console.log('Cache removed:', e.data.removed);
}
};
const messageChannel = new MessageChannel();
// Send the service worker a message to clear the cache.
// We can't use a BroadcastChannel for this because the
// service worker may need to be woken up. MessageChannels do that.
navigator.serviceWorker.controller.postMessage({
action: 'clearcache',
cacheName: 'v1-cache'
}, [messageChannel.port2]);
Di sw.js
function nukeCache(cacheName) {
return caches.delete(cacheName).then(removed => {
// ...do more stuff (internal) to this service worker...
return removed;
});
}
self.onmessage = function(e) {
const action = e.data.action;
const cacheName = e.data.cacheName;
if (action === 'clearcache') {
nukeCache(cacheName).then(removed => {
// Send the main page a response via the BroadcastChannel API.
// We could also use e.ports[0].postMessage(), but the benefit
// of responding with the BroadcastChannel API is that other
// subscribers may be listening.
const channel = new BroadcastChannel('app-channel');
channel.postMessage({action, removed});
});
}
};
Perbedaan dengan postMessage()
Tidak seperti postMessage()
, Anda tidak perlu lagi mempertahankan referensi ke iframe atau pekerja untuk berkomunikasi dengannya:
// Don't have to save references to window objects.
const popup = window.open('https://another-origin.com', ...);
popup.postMessage('Sup popup!', 'https://another-origin.com');
window.postMessage()
juga memungkinkan Anda berkomunikasi di seluruh origin. Broadcast Channel API memiliki origin yang sama. Karena pesan dijamin berasal dari asal yang sama, Anda tidak perlu memvalidasinya seperti yang biasa dilakukan dengan window.postMessage()
:
// Don't have to validate the origin of a message.
const iframe = document.querySelector('iframe');
iframe.contentWindow.onmessage = function(e) {
if (e.origin !== 'https://expected-origin.com') {
return;
}
e.source.postMessage('Ack!', e.origin);
};
Cukup "subscribe" ke saluran tertentu dan lakukan komunikasi dua arah yang aman.
Perbedaan dengan SharedWorkers
Gunakan BroadcastChannel
untuk kasus sederhana saat Anda perlu mengirim pesan ke beberapa jendela/tab, atau pekerja.
Untuk kasus penggunaan yang lebih canggih seperti mengelola kunci, status bersama, menyinkronkan resource antara server dan beberapa klien, atau berbagi koneksi WebSocket dengan host jarak jauh, pekerja bersama adalah solusi yang paling sesuai.
Perbedaan dengan MessageChannel API
Perbedaan utama antara Channel Messaging API dan BroadcastChannel
adalah bahwa yang terakhir adalah cara untuk mengirim pesan ke beberapa pemroses (satu ke banyak). MessageChannel
dimaksudkan untuk komunikasi satu lawan satu secara langsung antar-skrip. Cara ini juga lebih rumit, karena Anda harus menyiapkan saluran dengan port di setiap ujungnya.
Deteksi fitur dan dukungan browser
Saat ini, Chrome 54, Firefox 38, dan Opera 41 mendukung Broadcast Channel API.
if ('BroadcastChannel' in self) {
// BroadcastChannel API supported!
}
Untuk polyfill, ada beberapa polyfill yang tersedia:
- https://gist.github.com/alexis89x/041a8e20a9193f3c47fb
- https://gist.github.com/inexorabletash/52f437d1451d12145264
Saya belum mencobanya, jadi pengalaman Anda mungkin berbeda.