SharedWorkerGlobalScope属性数据共享示例解析
作者:田八
引言
上一章介绍了Worker的全局作用域,了解到DedicatedWorkerGlobalScope是继承自WorkerGlobalScope的;
这一章介绍的SharedWorkerGlobalScope也是继承自WorkerGlobalScope的,那么SharedWorkerGlobalScope和DedicatedWorkerGlobalScope有什么区别呢?
SharedWorkerGlobalScope
SharedWorkerGlobalScope和DedicatedWorkerGlobalScope一样都是一个全局作用域,它的实例是SharedWorker,它的原型是WorkerGlobalScope,它的构造函数是SharedWorkerGlobalScope。
在SharedWorker中可以使用self关键字来访问SharedWorkerGlobalScope的实例,也可以使用this关键字来访问SharedWorkerGlobalScope的实例。

他们之间的关系如上图所示。
SharedWorkerGlobalScope的属性
SharedWorkerGlobalScope的属性大多数和DedicatedWorkerGlobalScope一样,只是少了onmessage和onerror,因为SharedWorkerGlobalScope是多个DedicatedWorkerGlobalScope共享的,所以SharedWorkerGlobalScope的onmessage和onerror是多个DedicatedWorkerGlobalScope共享的。
这里直接通过函数签名的方式来介绍SharedWorkerGlobalScope的属性。
interface SharedWorkerGlobalScope extends WorkerGlobalScope {
readonly name: string;
close(): void;
onconnect: EventHandler
}
name:SharedWorkerGlobalScope的名字,它是只读的,只能在SharedWorker的构造函数中设置,如果使用相同的name创建多个SharedWorker,那么它们会共享同一个SharedWorkerGlobalScope。close():关闭SharedWorkerGlobalScope,它会丢弃所有的等待执行的任务。onconnect:当有新的DedicatedWorkerGlobalScope连接到SharedWorkerGlobalScope时,会触发onconnect事件。
可以对比一下DedicatedWorkerGlobalScope的属性,其实相差不大,只是少了onmessage和onerror,多了onconnect。
数据共享
DedicatedWorkerGlobalScope是通过postMessage来与DedicatedWorkerGlobalScope通信的,而SharedWorkerGlobalScope是通过onconnect来与DedicatedWorkerGlobalScope通信的。
SharedWorkerGlobalScope的onconnect事件会返回一个MessagePort,它是一个双向的通信通道,可以通过它来与DedicatedWorkerGlobalScope通信。
interface MessagePort extends EventTarget {
readonly name: string;
close(): void;
postMessage(message: any, transfer?: Transferable[]): void;
start(): void;
onmessage: EventHandler;
onmessageerror: EventHandler;
}
看函数签名可以发现MessagePort也是继承自EventTarget的,这就意味着MessagePort也可以使用addEventListener来监听事件。
MessagePort自带的属性和方法不难发现和DedicatedWorkerGlobalScope的是相同的,只是多了一个sart方法。
不同于DedicatedWorkerGlobalScope的是,MessagePort是双向的,或者说MessagePort是双向的一边,两个MessagePort形成一个双向的通信通道。
MessagePort是Channel Messaging API的一部分,这又引出了Channel Messaging API。
Channel Messaging API
Channel Messaging API允许我们创建一个双向的通信通道,它的实例是MessageChannel,它的原型是EventTarget,它的构造函数是MessageChannel。
interface MessageChannel extends EventTarget {
readonly port1: MessagePort;
readonly port2: MessagePort;
}
可以看到MessageChannel有两个只读属性,分别是port1和port2,它们都是MessagePort的实例,它们之间形成一个双向的通信通道。
const channel = new MessageChannel();
channel.port1.onmessage = (event) => {
console.log(event.data);
};
channel.port2.postMessage('hello');
上面的代码中,channel.port1和channel.port2是一个双向的通信通道,它们之间可以互相通信。
当然通常我们不会这样使用MessageChannel,那可以用来做什么呢,我们可以实现数据拷贝:
const channel = new MessageChannel();
channel.port1.onmessage = (event) => {
console.log(event.data);
};
var obj = { a: 1 };
obj.b = obj;
channel.port2.postMessage(obj);
这里使用的是结构化克隆算法,它可以克隆复杂的数据结构,而不是简单的拷贝引用。
SharedWorker
当我们了解了SharedWorkerGlobalScope、MessagePort、MessageChannel之后,我们对SharedWorker的使用就不会陌生了。
// main.js
const worker = new SharedWorker('worker.js', 'worker');
worker.port.onmessage = (event) => {
console.log(event.data);
};
// 在讲 SharedWorker 的文章中讲过
// 如果使用 onmessage 监听,会自动调用 start 方法
// 如果使用 addEventListener 监听,需要手动调用 start 方法
// 所以下面的代码可以省略
worker.port.start();
worker.port.postMessage('hello');
当我们有上面的基础之后,来看一下上面构建的SharedWorker的代码,不难发现都是我们之前讲过的:
new SharedWorker:是SharedWorker的构造函数,这个是属于SharedWorker的worker.port:是MessagePort的实例,也是属于SharedWorker的worker.port.onmessage:是MessagePort的onmessage事件worker.port.start():是MessagePort的start方法worker.port.postMessage:是MessagePort的postMessage方法
通过上面的代码就可以推断出SharedWorker的函数签名:
interface SharedWorker extends EventTarget {
constructor(scriptURL: string, name?: string);
readonly port: MessagePort;
}
事实的函数签名也是和上面的一致。
上面是在主函数中创建SharedWorker,那么在SharedWorker中是怎么使用的呢,我们来看一下:
// worker.js
onconnect = (event) => {
const port = event.ports[0];
port.onmessage = (event) => {
console.log(event.data);
};
port.start();
port.postMessage('hello');
};
在SharedWorker中,只需要监听onconnect事件,然后在事件中获取MessagePort,然后就可以使用MessagePort的方法了。
这个是属于SharedWorkerGlobalScope的,可以把文章网上翻翻,就可以看到了。
总结
通过这次分析SharedWorkerGlobalScope之后,我们对SharedWorker的使用就不会陌生了;
它的使用和Worker是一样的,不同是他们的全局作用域不同,只是会有一些特定的方法,都是WorkerGlobalScope的子类,所以它可以使用WorkerGlobalScope的所有方法。
也通过这次分析,我们认识到MessagePort、MessageChannel,这些都是SharedWorker的基础也是核心,它们之间的关系也是非常重要的。
而且认识到MessagePort、MessageChannel之后,其实跨页面通信也可以使用它们,也可以使用它们来做一些其他的事情,这些就看自己的想象力了。
以上就是SharedWorkerGlobalScope属性数据共享示例解析的详细内容,更多关于SharedWorkerGlobalScope属性的资料请关注脚本之家其它相关文章!
