BroadcastChannel API - Web için bir mesaj yolu

BroadcastChannel API, aynı kaynaklı komut dosyalarının diğer tarama bağlamlarına mesaj göndermesine izin verir. Pencereler/sekmeler, iframe'ler, web çalışanları ve Service Worker'lar arasında pub/sub semantiğine izin veren basit bir mesaj yolu olarak düşünülebilir.

API temel bilgileri

Broadcast Channel API, tarama bağlamları arasında iletişim kurmayı kolaylaştıran basit bir API'dir. Yani pencereler/sekmeler, iframe'ler, web çalışanları ve hizmet çalışanları arasında iletişim kurulur. Belirli bir kanalda yayınlanan mesajlar, söz konusu kanalın tüm dinleyicilerine iletilir.

BroadcastChannel oluşturucu tek bir parametre alır: kanalın adı. Kanal adı, kanalı tanımlar ve göz atma bağlamlarında bulunur.

// 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();

İleti gönderme

Mesajlar, dizeler veya yapılandırılmış klon algoritması tarafından (Dizeler, Nesneler, Diziler, Blob'lar, ArrayBuffer, Harita) desteklenen herhangi bir şey olabilir.

Örnek: Blob veya Dosya gönderme

channel.postMessage(new Blob(['foo', 'bar'], {type: 'plain/text'}));

Bir kanal kendi kendine yayın yapmaz. onmessage dinleyiciniz varsa o message etkinliğindeki postMessage() ile aynı sayfada tetiklenmez.

Diğer tekniklerden farkları

Bu noktada bunun WebSockets, SharedWorkers, MessageChannel API ve window.postMessage() gibi diğer mesaj iletme teknikleriyle nasıl bir ilişkisi olduğunu merak ediyor olabilirsiniz. Broadcast Channel API, bu API'lerin yerini almaz. Her biri bir amaca hizmet eder. Broadcast Channel API'nin amacı, aynı kaynaktaki komut dosyaları arasında bire-çok kolay iletişim sağlamaktır.

Yayın kanalları için bazı kullanım örnekleri:

  • Diğer sekmelerdeki kullanıcı işlemlerini algıla
  • Kullanıcının başka bir pencerede/sekmede hesaba giriş yaptığını görün.
  • Bir çalışandan arka planda bir şeyler yapmasını isteyin
  • Bir hizmetin, bazı işlemleri ne zaman tamamladığını öğrenme.
  • Kullanıcı bir pencerede bir fotoğraf yüklediğinde, bunu diğer açık sayfalara iletin.

Örnek – aynı sitedeki başka bir açık sekmeden bile, kullanıcının ne zaman çıkış yaptığını bilen sayfa:

<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>

Başka bir örnekte, bir hizmet çalışanına bir öğeyi kaldırmasını Kullanıcı "çevrimdışı depolama alanı ayarını" değiştirdikten sonra önbelleğe alınan içerik dokunun. window.caches kullanarak önbelleklerini silebilirsiniz, ancak hizmet çalışanı bunu yapacak bir yardımcı program içerir. Broadcast Channel API'yi kullanarak o kodu tekrar kullanın! Broadcast Channel API olmadan bir hizmet çalışanının tüm müşterilerine yönelik iletişimi gerçekleştirebilmek için self.clients.matchAll() sonuçlarını döngüye almanız ve her istemcide postMessage() çağrısı yapmanız gerekir (bunu yapan gerçek kod). Bir Yayın Kanalı kullanırsanız O(N) yerine bu O(1) yapılır.

Örnek: Bir hizmet çalışanına, dahili yardımcı program yöntemlerini yeniden kullanarak önbelleği kaldırması talimatı verme.

index.html içinde

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]);

sw.js'de

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});
    });
    }
};

postMessage() ile fark

postMessage()'nin aksine, artık bir iframe veya çalışanla iletişim kurmak için ona referans olması gerekmez:

// 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() ayrıca kaynaklar arasında iletişim kurmanızı sağlar. Broadcast Channel API aynı kaynaklıdır. İletilerin aynı kaynaktan gelmesi garanti edildiğinden, bunları window.postMessage() ile yaptığımız gibi doğrulamaya gerek yoktur:

// 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);
};

"Abone ol" yazmanız yeterlidir güvenli ve çift yönlü güvenli iletişim kurmanıza yardımcı olabilir.

SharedWorkers ile Fark

Birkaç pencereye/sekmeye veya çalışanlara ileti göndermenizin gerektiği basit durumlarda BroadcastChannel politikasını kullanın.

Kilitleri yönetme, paylaşılan durum, kaynakları bir sunucu ile birden çok istemci arasında senkronize etme veya uzak bir ana makineyle WebSocket bağlantısını paylaşma gibi daha ilginç kullanım alanları için paylaşılan çalışanlar en uygun çözümdür.

MessageChannel API ile farkı

Channel Messaging API ile BroadcastChannel arasındaki temel fark, ikincisinin birden çok dinleyiciye (bire-çok) mesaj gönderme aracı olmasıdır. MessageChannel, doğrudan komut dosyaları arasında bire bir iletişim içindir. Bu süreç daha karmaşıktır ve iki ucunda bir bağlantı noktası bulunan kanallar oluşturmanız gerekir.

Özellik algılama ve tarayıcı desteği

Şu anda Chrome 54, Firefox 38 ve Opera 41, Broadcast Channel API'yi desteklemektedir.

if ('BroadcastChannel' in self) {
    // BroadcastChannel API supported!
}

Polyfill'ler için kullanabileceğiniz birkaç yöntem var:

Bunları denemediğim için kilometreniz değişiklik gösterebilir.

Kaynaklar