最近,BroadcastChannel API 已在 Firefox 38 中发布。此 API 可用于在具有相同用户代理和来源的浏览器上下文之间进行简单消息传递。此 API 向 Windows 和 Workers 公开,并允许在 iframe、浏览器标签和 worker 线程之间进行通信。
BroadcastChannel API 的目的是提供一个 API,以促进 Web 应用程序中浏览器上下文之间简单消息的通信。例如,当用户登录应用程序中的某个页面时,它可以将用户的信息更新到所有其他上下文(例如,标签或单独的窗口),或者如果用户将照片上传到浏览器窗口,则图像可以传递到应用程序中的其他打开页面。此 API 不打算处理复杂的运算,例如共享资源锁定或将多个客户端与服务器同步。在这种情况下,共享 worker 更合适。
API 概述
可以使用以下代码创建 BroadcastChannel 对象
var myChannel = new BroadcastChannel("channelname");
channelname 区分大小写。BroadcastChannel 实例包含两个方法:postMessage 和 close。postMessage 方法用于向通道发送消息。消息内容可以是任何对象,包括复杂的对象,例如图像、数组和对象数组。发布消息时,将通知具有相同来源、用户代理和具有相同 channelname 的 BroadcastChannel 的所有浏览器上下文该消息。例如,以下代码发布了一个简单的字符串
myChannel.postMessage("Simple String");
通过使用 BroadcastChannel 实例的 onmessage 事件处理程序,任何打开了通道的页面都可以处理分派的 message。
myChannel.onmessage = function(event) {
console.log(event.data);
}
请注意,事件的 data 属性包含消息的数据。事件的其他属性也可能有用。例如,可以使用 event.origin 属性检查 Web 应用程序来源,或者 event.target.name 属性中提供 channel name。
close 方法用于关闭特定浏览器上下文的通道,可以使用以下方法调用:
broadCastChannel.close();
Blob 消息发布
虽然发布字符串和其他原始类型非常简单,但 BroadcastChannel API 也支持更复杂的对象。例如,要将图像从一个上下文发布到另一个上下文,可以使用以下代码。
var broadcastExample = {};
broadcastExample.setupChannel = function() {
if ("BroadcastChannel" in window) {
if (typeof broadcastExample.channel === 'undefined' ||
!broadcastExample.channel) {
//create channel
broadcastExample.channel = new BroadcastChannel("foo");
}
}
}
broadcastExample.pMessage = function() {
broadcastExample.setupChannel();
//get image element
var img = document.getElementById("ffimg");
//create canvas with image
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
//get blob of canvas
canvas.toBlob(function(blob) {
//broadcast blob
broadcastExample.channel.postMessage(blob);
});
}
上面的代码包含两个函数,并代表 BroadcastChannel 客户端的发件方。setupChannel 方法只是打开 Broadcast Channel,而 pMessage 方法从页面检索图像元素并将其转换为 Blob。最后,Blob 发布到 BroadcastChannel。接收方页面需要已经监听 BroadcastChannel 才能接收消息,并且可以类似于以下内容进行编码。
var broadcastFrame = {};
//setup broadcast channel
broadcastFrame.setup = function() {
if ("BroadcastChannel" in window) {
if (typeof broadcastFrame.channel === 'undefined' || !broadcastFrame.channel) {
broadcastFrame.channel = new BroadcastChannel("foo");
}
//function to process broadcast messages
function func(e) {
if (e.data instanceof Blob) {
//if message is a blob create a new image element and add to page
var blob = e.data;
var newImg = document.createElement("img"),
url = URL.createObjectURL(blob);
newImg.onload = function() {
// no longer need to read the blob so it's revoked
URL.revokeObjectURL(url);
};
newImg.src = url;
var content = document.getElementById("content");
content.innerHTML = "";
content.appendChild(newImg);
}
};
//set broadcast channel message handler
broadcastFrame.channel.onmessage = func;
}
}
window.onload = broadcastFrame.setup();
此代码从广播消息获取 blob 并创建一个图像元素,该元素将添加到接收方页面。
Workers 和 BroadcastChannel 消息
BroadcastChannel API 也适用于专用和共享的 workers。作为一个简单的示例,假设启动了一个 worker,并且当通过主脚本向 worker 发送消息时,worker 然后将消息广播到 Broadcast Channel。
var broadcastExample = {};
broadcastExample.setupChannel = function() {
if ("BroadcastChannel" in window) {
if (typeof broadcastExample.channel === 'undefined' ||
!broadcastExample.channel) {
//create channel
broadcastExample.channel = new BroadcastChannel("foo");
}
}
}
function callWorker() {
broadcastExample.setupChannel();
//verify compat
if (!!window.Worker) {
var myWorker = new Worker("worker.js");
//ping worker to post to Broadcast Channel
myWorker.postMessage("Broadcast from Worker");
}
}
//Worker.js
onmessage = function(e) {
//Broadcast Channel Message with Worker
if ("BroadcastChannel" in this) {
var workerChannel = new BroadcastChannel("foo");
workerChannel.postMessage("BroadcastChannel Message Sent from Worker");
workerChannel.close();
}
}
可以通过与本文前面部分中描述的相同方式在主页面中处理该消息。
使用 Worker 将消息广播到 iframe
更多信息
除了演示如何在 iframe 中使用外,本文中的代码还提供另一个示例,该示例介绍了如何在 github 上使用该代码。有关 BroadcastChannel API 的更多信息,请参阅 规范、bugzilla 条目 和 MDN。该 API 的代码和测试页面位于 gecko 源代码 中。
8 条评论