怎么使用Web Workers提升性能?

2023-11-06

一、概述

Web Workers 使得一个Web应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作。这样做的好处是可以在一个单独的线程中执行费时的处理任务,从而允许主(通常是UI)线程运行而不被阻塞。

它的作用就是给JS创造多线程运行环境,允许主线程创建worker线程,分配任务给后者,主线程运行的同时worker线程也在运行,相互不干扰,在worker线程运行结束后把结果返回给主线程。这样做的好处是主线程可以把计算密集型或高延迟的任务交给worker线程执行,这样主线程就会变得轻松,不会被阻塞或拖慢。这并不意味着JS语言本身支持了多线程能力,而是浏览器作为宿主环境提供了JS一个多线程运行的环境。

不过因为worker一旦新建,就会一直运行,不会被主线程的活动打断,这样有利于随时响应主线程的通性,但是也会造成资源的浪费,所以不应过度使用,用完注意关闭。或者说:如果worker无实例引用,该worker空闲后立即会被关闭;如果worker实列引用不为0,该worker空闲也不会被关闭。

二、使用场景

前端过程中,如果遇到一些大量耗时的运用场景,我们可以采用web worker,新建线程,来提升主线程的运行流畅性,提升性能。可能场景如下:

  • 加密数据

    有些加解密的算法比较复杂,或者在加解密很多数据的时候,这会非常耗费计算资源,导致UI线程无响应,因此这是使用Web Worker的好时机,使用Worker线程可以让用户更加无缝的操作UI。

  • 预取数据

    有时候为了提升数据加载速度,可以提前使用Worker线程获取数据,因为Worker线程是可以是用 XMLHttpRequest 的。

  • 预渲染

    在某些渲染场景下,比如渲染复杂的canvas的时候需要计算的效果比如反射、折射、光影、材料等,这些计算的逻辑可以使用Worker线程来执行,也可以使用多个Worker线程,这里有个射线追踪的示例

  • 复杂数据处理

    某些检索、排序、过滤、分析会非常耗费时间,这时可以使用Web Worker来进行,不占用主线程。

  • 预加载图片

    有时候一个页面有很多图片,或者有几个很大的图片的时候,如果业务限制不考虑懒加载,也可以使用Web Worker来加载图片,可以参考一下这篇文章的探索,这里简单提要一下。

三、语法

Worker() 构造函数创建一个 Worker 对象,该对象执行指定的 URL 脚本。这个脚本必须遵守 同源策略

const myWorker = new Worker(aURL, options);

1、参数

  • 如果文档不允许启动 worker,则会引发 SecurityError

  • 如果脚本之一的 MIME 类型为 text/csv, image/*, video/*,或 audio/*, 则会引发 NetworkError。它应该始终是 text/javascript。

  • 如果 aURL 无法解析,则引发 SyntaxError。

  • aURL

    • : 是一个DOMString 表示 worker 将执行的脚本的 URL。它必须遵守同源策略。
  • options

    可选

    • : 包含可在创建对象实例时设置的选项属性的对象。可用属性如下:
      • type:用以指定 worker 类型的 DOMString 值。该值可以是 classicmodule. 如果未指定,将使用默认值 classic.
      • credentials:用以指定 worker 凭证的 DOMString 值。该值可以是* omit*, same-origin,或 include.。如果未指定,或者 type 是 classic,将使用默认值 omit (不要求凭证)。
      • *name:*在 DedicatedWorkerGlobalScope 的情况下,用来表示 worker 的 scope 的一个 DOMString 值,主要用于调试目的。

2、返回值

创建的 worker。

五、使用

1、常驻内存

index.vue代码

<template>
    web worker
    <el-button @click="save" type="primary">保存</el-button>
</template>
<script setup lang="ts">
import { onMounted } from "vue";

const saveWorker = new Worker(
    new URL("./worker.ts", import.meta.url),
    {
        type: "module",
    }
);
saveWorker.onmessage = (e: any) => {
    if (e.data.error) {
        console.error("自动保存失败,请联系管理员!");
    } else {
        console.log("自动保存成功!");
    }
};
const save = () => {
    saveWorker.postMessage({
        frameData: { a: 1, b: 2 },
        editorToken: "123456",
    });

}
onMounted(() => {
})
</script>

<style lang="scss"></style>

worker.ts代码:

import axios from "axios";

self.addEventListener("message", async (e) => {
    const frameData = e.data.frameData;
    const token = e.data.editorToken;
    let params = { frameData, token };
    let res = await axios({
        url: "/api/get",
        method: "get",
        params: params,
    })
    if (res.data.code !== 0) {
        // worker线程发送消息
        (self as any).postMessage({
            error: true,
        });
        return;
    }
    // worker线程发送消息
    (self as any).postMessage({
        error: false,
        data: res.data.data
    });
});

export { };

2、临时使用

index.vue代码

//index.vue
<template>
    web worker
    <el-button @click="save" type="primary">保存</el-button>
</template>
<script setup lang="ts">
import { onMounted } from "vue";

const save = () => {
    //每次使用都单独创建
    const saveWorker = new Worker(
        new URL("./worker.ts", import.meta.url),
        {
            type: "module",
        }
    );
    saveWorker.onmessage = (e: any) => {
        if (e.data.error) {
            console.error("自动保存失败,请联系管理员!");
        } else {
            console.log("自动保存成功!");
        }
    };
    saveWorker.postMessage({
        frameData: { a: 1, b: 2 },
        editorToken: "123456",
    });

}
onMounted(() => {
})
</script>

<style lang="scss"></style>

worker.ts代码:

//worker.ts
import axios from "axios";

self.addEventListener("message", async (e) => {
    //...同上

    (self as any).close();//用完就关闭
});

export { };

六、使用限制

worker线程的使用有一些注意点

  1. 同源限制
    worker线程执行的脚本文件必须和主线程的脚本文件同源,这是当然的了,总不能允许worker线程到别人电脑上到处读文件吧
  2. 文件限制
    为了安全,worker线程无法读取本地文件,它所加载的脚本必须来自网络,且需要与主线程的脚本同源
  3. DOM操作限制
    worker线程在与主线程的window不同的另一个全局上下文中运行,其中无法读取主线程所在网页的DOM对象,也不能获取 documentwindow等对象,但是可以获取navigatorlocation(只读)XMLHttpRequestsetTimeout族等浏览器API。
  4. 通信限制
    worker线程与主线程不在同一个上下文,不能直接通信,需要通过postMessage方法来通信。
  5. 脚本限制
    worker线程不能执行alertconfirm,但可以使用 XMLHttpRequest 对象发出ajax请求。

MDN官网对Worker的说明

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

怎么使用Web Workers提升性能? 的相关文章

随机推荐

  • ROS机器人构建和深度学习应用

    机器人操作系统是机器人研究和公司建模 模拟和原型机器人使用最广泛的软件框架之一 将您的 ROS 知识应用于实际机器人技术比人们意识到的要困难得多 但是这个标题将立即为您提供创建自己的机器人技术所需的一切 包含超过 14 个 ROS 机器人项
  • python中input()函数详解

    1 input 函数赋值后数据在python内部的类型 if name main a input print type a b input print type b c a b print c print type c 输入及输出 从结果可
  • 解决Anaconda环境未激活的warning

    在cmd内键入python之后会报Warning 显示Anaconda环境未激活 使用如下命令激活 conda activate base 这里base指环境名 默认为base 查看环境名可以用如下命令 conda info envs
  • Oracle常见问题定位方法

    Oracle在安装时无法正常显示出安装界面 现象 在vnc的界面中 安装时提示 Can t connect to X11 window server using 1 0 as the value of the DISPLAY variabl
  • 使用注解开发springmvc

    第三步 pom xml文件引入相关依赖 主要有Spring框架核心库 Spring MVC servlet JSTL等 第四步 配置web xml 映射路径 不要为 会404 第六步 创建Controller RequestMapping
  • 某宝滑块ua特征研究

    从137版本开始某宝新加了x 82类型滑块 和之前无感或者滑动验证js 类似 不过浏览器特征检测 反调试干扰都增加了不少 变得更有难度 下面稍微讲下研究过程 首先处理大量三目运算符 这个没啥好办法 博主用ast处理的 类似下面这种 单步调试
  • 贪心算法求解TSP问题(python)

    这里使用贪心算法求解TSP问题的python版本 dist 为距离矩阵 start index 为起始位置 def tsp quick dist list start index int sum distance seq result n
  • 用C++做一颗会跳动的爱心

    先来看看效果 程序描述 程序先以较慢的速度画一个大爱心 之后跳动的心其实从视觉上看就是一大一小两个心相互切换 但是要调整一下大小爱心变化时的时间间隔 代码主要是通过设置两个函数 利用cls来清屏 重复打印大心和小心 并设置颜色为红色 详细代
  • php公众号获取code,微信公众号获取code

    methods getCode 非静默授权 第一次有弹框 this code var local window location href 获取页面url var appid wx65adcf075369 this code this ge
  • 使用LFM(Latent factor model)隐语义模型进行Top-N推荐

    最近在拜读项亮博士的 推荐系统实践 系统的学习一下推荐系统的相关知识 今天学习了其中的隐语义模型在Top N推荐中的应用 在此做一个总结 隐语义模型LFM和LSI LDA Topic Model其实都属于隐含语义分析技术 是一类概念 他们在
  • Windows 下如何安装配置Snort视频教程

    Windows 下如何安装配置Snort视频教程 第一步 http www tudou com programs view UUbIQCng360 第二部 http www tudou com programs view NqcPETQk2
  • 【算法】算法学习三:递归算法 & 栈

    文章目录 一 递归的含义 二 基线条件和递归条件 三 栈 3 1 什么是栈 3 2 调用栈 3 3 递归调用栈 一 递归的含义 递归算法是一种解决问题的方法 其中函数在执行过程中调用自身 它通过将一个大问题拆分成一个或多个相似的子问题 并逐
  • 数据倾斜2

    数据倾斜的原因和解决方案 MapReduce简介 MapReduce是面向大数据并行处理的计算模型 框架和平台 它隐含了以下三层含义 1 MapReduce是一个基于集群的高性能并行计算平台 Cluster Infrastructure 它
  • 文件上传到Linux服务器常用方法

    本文介绍几种常见的方法 把文件上传到Linux服务器中 常见有使用 scp命令 xshell软件里的xftp程序 U盘挂载 服务器自带的lrzsz程序 一 scp使用说明 1 把本机的文件传给目的服务器 linux linux scp ge
  • 修改Windows的git bash的主题(样式)

    背景 Windows的git bash页面默认是黑白的 如何改成别的颜色 PS 我一直不太喜欢黑色主题的软件 有几个原因 大多软件是白色的 看久了黑色切换到其他软件的时候眼睛不适应 字体等对比不强 我真的不知道为啥这么多人喜欢IDEA黑色主
  • 数组类型方法

    数组类型方法 1 concat 创建一个新数组 将array与任何数组 或 值连接在一起 let arr 1 2 3 4 let arr2 9 let arr3 arr concat arr2 console log arr3 1 2 3
  • jQuery操作类样式(增加、移除、判断)

    一 增加和移除一个或多个类样式的方法 1 增加一个类样式的方法 1 当前需要增加样式的元素 addClass cls 注意在addClass方法中类样式的名字前面没有点 2 增加多个类样式的方法 1 第一种写法 当前需要增加样式的元素 ad
  • 最新Landsat数据下载教程

    目前 国内下载Landsat数据可以通过USGS网站或者地理空间数据云下载 由于USGS对Landsat数据进行了修改 地理空间数据云目前只存储有2017年5月之前的数据 本文只介绍从USGS网站下载Landsat数据 USGS有两个网站可
  • mysql: using the Connector/J connection property ‘autoReconnect=true‘ to avoid this problem

    报错信息 com mysql cj jdbc exceptions CommunicationsException The last packet successfully received from the server was 1 12
  • 怎么使用Web Workers提升性能?

    一 概述 Web Workers 使得一个Web应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作 这样做的好处是可以在一个单独的线程中执行费时的处理任务 从而允许主 通常是UI 线程运行而不被阻塞 它的作用就是给JS创造多线程运行