BroadcastChannel API به اسکریپت های با منبع یکسان اجازه می دهد تا پیام هایی را به سایر زمینه های مرور ارسال کنند. میتوان آن را بهعنوان یک گذرگاه پیام ساده در نظر گرفت که به معنای pub/sub بین پنجرهها/تبها، iframe، وبکارگران و سرویسدهندگان اجازه میدهد.
اصول API
Broadcast Channel API یک API ساده است که برقراری ارتباط بین زمینه های مرور را آسان تر می کند. یعنی برقراری ارتباط بین ویندوز / تب ها، iframe ها، وب کارگران و سرویسکاران. پیامهایی که به یک کانال ارسال میشوند به همه شنوندگان آن کانال ارسال میشوند.
سازنده BroadcastChannel
یک پارامتر واحد را می گیرد: نام یک کانال. نام کانال را مشخص می کند و در زمینه های مرور زندگی می کند.
// 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();
ارسال پیام
پیامها میتوانند رشتهها یا هر چیزی که توسط الگوریتم کلون ساختیافته پشتیبانی میشود (رشتهها، اشیاء، آرایهها، Blobs، ArrayBuffer، Map) باشند.
به عنوان مثال - ارسال یک Blob یا فایل
channel.postMessage(new Blob(['foo', 'bar'], {type: 'plain/text'}));
یک کانال برای خودش پخش نمی شود. بنابراین اگر یک شنونده onmessage
در همان صفحه با یک postMessage()
به همان کانال دارید، آن رویداد message
فعال نمیشود.
تفاوت با سایر تکنیک ها
در این مرحله ممکن است تعجب کنید که این چگونه با سایر تکنیکهای ارسال پیام مانند WebSockets، SharedWorkers، MessageChannel
API و window.postMessage()
ارتباط دارد. Broadcast Channel API جایگزین این APIها نمی شود. هر کدام هدفی را دنبال می کند. Broadcast Channel API برای برقراری ارتباط آسان یک به چند بین اسکریپت ها در یک مبدا طراحی شده است.
برخی از موارد استفاده برای کانال های پخش:
- اقدامات کاربر را در برگه های دیگر شناسایی کنید
- زمانی که کاربر در پنجره/برگه دیگری وارد حساب کاربری می شود، بدانید.
- به یک کارگر دستور دهید تا برخی از کارهای پس زمینه را انجام دهد
- بدانید چه زمانی یک سرویس با انجام برخی اقدامات انجام می شود.
- هنگامی که کاربر عکسی را در یک پنجره آپلود می کند، آن را به سایر صفحات باز ارسال کنید.
مثال - صفحه ای که می داند چه زمانی کاربر از سیستم خارج می شود، حتی از یک برگه باز دیگر در همان سایت:
<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>
در مثالی دیگر، فرض کنید میخواستید به یک سرویسدهنده دستور دهید تا محتوای ذخیرهشده را پس از اینکه کاربر «تنظیمات ذخیرهسازی آفلاین» خود را در برنامه شما تغییر داد، حذف کند. میتوانید حافظه پنهان آنها را با استفاده از window.caches
حذف کنید، اما سرویسکار ممکن است قبلاً دارای یک ابزار برای انجام این کار باشد. ما می توانیم از Broadcast Channel API برای استفاده مجدد از آن کد استفاده کنیم! بدون Broadcast Channel API، شما باید نتایج self.clients.matchAll()
را حلقه بزنید و با postMessage()
روی هر کلاینت تماس بگیرید تا ارتباط یک سرویس دهنده با همه مشتریانش برقرار شود ( کد واقعی که آن را انجام می دهد ). استفاده از کانال پخش، این O(1)
را به جای O(N)
می کند.
مثال - به یک سرویسگر دستور دهید تا یک حافظه پنهان را با استفاده مجدد از روشهای ابزار داخلی آن حذف کند.
در 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]);
در 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});
});
}
};
تفاوت با postMessage()
برخلاف postMessage()
، دیگر لازم نیست برای برقراری ارتباط با یک iframe یا worker ارجاع دهید:
// 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()
همچنین به شما اجازه می دهد تا با مبداها ارتباط برقرار کنید. Broadcast Channel API یک منبع است . از آنجایی که تضمین شده است که پیامها از یک مبدا میآیند، نیازی به اعتبارسنجی آنها مانند گذشته با 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);
};
به سادگی در یک کانال خاص "مشترک شوید" و ارتباط ایمن و دو طرفه داشته باشید!
تفاوت با SharedWorkers
از BroadcastChannel
برای موارد ساده استفاده کنید که در آن شما نیاز به ارسال پیام به چندین پنجره/برگه یا کارگر دارید.
برای موارد استفاده جالبتر مانند مدیریت قفلها، حالت اشتراکگذاری شده، همگامسازی منابع بین یک سرور و چندین مشتری، یا اشتراکگذاری اتصال WebSocket با یک میزبان راه دور، کارگران اشتراکگذاری مناسبترین راهحل هستند.
تفاوت با MessageChannel API
تفاوت اصلی بین Channel Messaging API و BroadcastChannel
این است که دومی وسیله ای برای ارسال پیام به چندین شنونده (یک به چند) است. MessageChannel
برای ارتباط یک به یک به طور مستقیم بین اسکریپت ها در نظر گرفته شده است. همچنین بیشتر درگیر است و باید کانال هایی را با یک پورت در هر انتها تنظیم کنید.
تشخیص ویژگی و پشتیبانی مرورگر
در حال حاضر، Chrome 54، Firefox 38، و Opera 41 از Broadcast Channel API پشتیبانی می کنند.
if ('BroadcastChannel' in self) {
// BroadcastChannel API supported!
}
در مورد پلی فیل ها، چند مورد وجود دارد:
- https://gist.github.com/alexis89x/041a8e20a9193f3c47fb
- https://gist.github.com/inexorabletash/52f437d1451d12145264
من اینها را امتحان نکردم، بنابراین مسافت پیموده شده شما ممکن است متفاوت باشد.