SharedWorkerGlobalScope属性数据共享示例解析
田八 人气:0引言
上一章介绍了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
之后,其实跨页面通信也可以使用它们,也可以使用它们来做一些其他的事情,这些就看自己的想象力了。
加载全部内容