🎈🎈🎈SharedWorkerGlobalScope 居然只是看起来复杂

简介: 上一章介绍了Worker的全局作用域,了解到DedicatedWorkerGlobalScope是继承自WorkerGlobalScope的; 这一章介绍的SharedWorkerGlobalScop

上一章介绍了Worker的全局作用域,了解到DedicatedWorkerGlobalScope是继承自WorkerGlobalScope的;

这一章介绍的SharedWorkerGlobalScope也是继承自WorkerGlobalScope的,那么SharedWorkerGlobalScopeDedicatedWorkerGlobalScope有什么区别呢?

SharedWorkerGlobalScope

SharedWorkerGlobalScopeDedicatedWorkerGlobalScope一样都是一个全局作用域,它的实例是SharedWorker,它的原型是WorkerGlobalScope,它的构造函数是SharedWorkerGlobalScope

SharedWorker中可以使用self关键字来访问SharedWorkerGlobalScope的实例,也可以使用this关键字来访问SharedWorkerGlobalScope的实例。

graph LR
EventTarget --> WorkerGlobalScope
WorkerGlobalScope --> DedicatedWorkerGlobalScope
DedicatedWorkerGlobalScope --> Worker
WorkerGlobalScope --> SharedWorkerGlobalScope
SharedWorkerGlobalScope --> SharedWorker

他们之间的关系如上图所示。

SharedWorkerGlobalScope的属性

SharedWorkerGlobalScope的属性大多数和DedicatedWorkerGlobalScope一样,只是少了onmessageonerror,因为SharedWorkerGlobalScope是多个DedicatedWorkerGlobalScope共享的,所以SharedWorkerGlobalScopeonmessageonerror是多个DedicatedWorkerGlobalScope共享的。

这里直接通过函数签名的方式来介绍SharedWorkerGlobalScope的属性。

interface SharedWorkerGlobalScope extends WorkerGlobalScope {
   
    readonly name: string;

    close(): void;

    onconnect: EventHandler
}
  • nameSharedWorkerGlobalScope的名字,它是只读的,只能在SharedWorker的构造函数中设置,如果使用相同的name创建多个SharedWorker,那么它们会共享同一个SharedWorkerGlobalScope
  • close():关闭SharedWorkerGlobalScope,它会丢弃所有的等待执行的任务。
  • onconnect:当有新的DedicatedWorkerGlobalScope连接到SharedWorkerGlobalScope时,会触发onconnect事件。

可以对比一下DedicatedWorkerGlobalScope的属性,其实相差不大,只是少了onmessageonerror,多了onconnect

数据共享

DedicatedWorkerGlobalScope是通过postMessage来与DedicatedWorkerGlobalScope通信的,而SharedWorkerGlobalScope是通过onconnect来与DedicatedWorkerGlobalScope通信的。

SharedWorkerGlobalScopeonconnect事件会返回一个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形成一个双向的通信通道。

MessagePortChannel 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有两个只读属性,分别是port1port2,它们都是MessagePort的实例,它们之间形成一个双向的通信通道。

const channel = new MessageChannel();

channel.port1.onmessage = (event) => {
   
    console.log(event.data);
};

channel.port2.postMessage('hello');

上面的代码中,channel.port1channel.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

当我们了解了SharedWorkerGlobalScopeMessagePortMessageChannel之后,我们对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:是MessagePortonmessage事件
  • worker.port.start():是MessagePortstart方法
  • worker.port.postMessage:是MessagePortpostMessage方法

通过上面的代码就可以推断出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的所有方法。

也通过这次分析,我们认识到MessagePortMessageChannel,这些都是SharedWorker的基础也是核心,它们之间的关系也是非常重要的。

而且认识到MessagePortMessageChannel之后,其实跨页面通信也可以使用它们,也可以使用它们来做一些其他的事情,这些就看自己的想象力了。

历史章节和预告

目录
相关文章
|
前端开发 JavaScript 定位技术
threejs绘制风羽
threejs绘制风羽
791 0
|
11月前
|
人工智能
捣鼓AI做一本情绪拉满的2025夸夸日历
本项目介绍如何利用AI制作2025年夸夸日历,通过魔搭社区和Qwen-Coderde模型生成充满赞美语句的日历卡片。首先了解卡片结构,明确尺寸、颜色等设计元素,再通过结构化提示具体制作。用户只需输入日期,AI即可生成精美的日历卡片,带有旋转闪烁效果,赋予每一天特别的意义。新年将至,不妨为亲友定制一本充满情感的夸夸日历,让2025年的每一天都充满活力与温暖。
277 8
|
定位技术 调度
Pixi绘制各种图形
这篇文章作为Pixi.js入门教程的一部分,详细介绍了如何使用Pixi.js绘制各种基本图形,如矩形、圆角矩形、圆形和椭圆,并提供了具体的实现代码。
273 0
Pixi绘制各种图形
|
JavaScript 前端开发 API
【Vue 3】一个小巧玲珑的 Vue 组件切换动画库,开源且免费!!
【Vue 3】一个小巧玲珑的 Vue 组件切换动画库,开源且免费!!
【Vue 3】一个小巧玲珑的 Vue 组件切换动画库,开源且免费!!
|
Java Spring
No qualifying bean of type 'XXXXX' available
该文档描述了Spring框架中`org.springframework.beans.factory.NoSuchBeanDefinitionException`异常的处理方法,该异常是因为无法找到类型为`com.weblog.auth.mapper.UserMapper`的bean导致。解决办法包括在对应的Mapper上添加`@Mapper`注解,并在启动类上添加`@MapperScan`注解以扫描包含Mapper接口的文件夹。
1074 8
|
缓存 前端开发 JavaScript
React.memo 与 useMemo 超厉害!深入浅出带你理解记忆化技术,让 React 性能优化更上一层楼!
【8月更文挑战第31天】在React开发中,性能优化至关重要。本文探讨了`React.memo`和`useMemo`两大利器,前者通过避免不必要的组件重渲染提升效率,后者则缓存计算结果,防止重复计算。结合示例代码,文章详细解析了如何运用这两个Hook进行性能优化,并强调了合理选择与谨慎使用的最佳实践,助你轻松掌握高效开发技巧。
533 0
|
前端开发 JavaScript 开发者
【前端革新力】React与CSS-in-JS完美邂逅:从styled-components到emotion,全面解析样式管理新趋势的实战应用与优势剖析!
【8月更文挑战第31天】CSS-in-JS 作为一种新兴的样式管理方式,近年来在前端社区受到广泛关注。它将样式嵌入 JavaScript,实现了样式与逻辑的高度耦合,提升了开发效率并解决了全局样式污染等问题。本文通过具体代码示例,探讨 CSS-in-JS 在 React 开发中的应用,并分享实践心得。首先介绍了 CSS-in-JS 的基本概念,然后详细展示了如何使用 styled-components 和 emotion 这两个流行库创建样式化组件。
705 0
|
Java Maven
解决 idea maven plugins 报红波浪线
解决 idea maven plugins 报红波浪线
2628 5
scrollIntoView()定位元素显示导致页面上移解决方法?
scrollIntoView()定位元素显示导致页面上移解决方法?
1157 0