Web前端入门第 86 问:JavaScript 中的 Web Worker 为什么能提升代码性能?

最初的 JS 执行代码都是一条线执行到底,当遇到比较耗时的操作时,比如大数组循环运算,就会导致页面卡着,就像假死一样。就像一个人在厨房烧菜一样,需要依次完成切菜、炒菜、装盘这些步骤,此过程中没办法同时做其他事情,必须按顺序执行每一个步骤。

Web Worker 赋予了 JS 分配任务的能力,在遇到复杂的计算型任务时,比如 canvas 图形图像处理(添加滤镜、矩阵变换等),此类不依赖 DOM 操作的计算型任务都可以交由 Web Worker 来处理,这样不会阻塞主线程的任务调度,从而提升前端的代码运行速度。

任务时序图

1

模拟耗时任务

看如下代码,使用一个超大的 for 循环,模拟 JS 中的耗时任务,让代码执行时主线程卡顿,还原假死现象:

/* by 01022.hk - online tools website : 01022.hk/zh/imagetoemf.html */
<div id="output"></div>
<button id="start">开始复杂任务</button>

<script>
  (() => {
    let times = 0
    const output = document.getElementById('output')

    function loop () {
      setTimeout(() => {
        times ++
        output.innerText = times
        loop()
      }, 1000);
    }
    loop()

    document.getElementById('start').addEventListener('click', () => {
      let n = 0
      console.time('任务耗时')
      for (let i = 0; i < 10000000000; i++) {
        n += i
      }
      console.timeEnd('任务耗时')
    })
  })();
</script>

执行结果:

2

可以看到点击 开始复杂任务 按钮时,在计时器的第 4 秒主线程卡主了将近 4 秒,然后再恢复运行,这就是单线程中的 JS 耗时任务导致的页面假死现象。

使用 Web Worker 解决耗时问题

看了上面的耗时任务导致页面假死,再使用 Web Worker 来重写一下上面代码:

main.html

/* by 01022.hk - online tools website : 01022.hk/zh/imagetoemf.html */
<div id="output"></div>
<button id="start">开始复杂任务</button>

<script>
  (() => {
    let times = 0
    const output = document.getElementById('output')

    function loop () {
      setTimeout(() => {
        times ++
        output.innerText = times
        loop()
      }, 1000);
    }
    loop()

    const worker = new Worker('./worker.js')
    worker.onmessage = event => {
      // 子线程计算结果
      console.log(event.data)
      console.timeEnd('任务耗时')
    }
    worker.onerror = event => {
      console.error('Worker 异常:', event)
    }
    document.getElementById('start').addEventListener('click', () => {
      console.time('任务耗时')
      worker.postMessage(10000000000)
    })
  })();
</script>

worker.js

// worker.js
self.onmessage = event => {
  let n = 0
  let max = event.data
  for (let i = 0; i < max; i++) {
    n += i
  }
  postMessage(n)
}

执行结果:

3

可以看到虽然任务耗时长短差不多,但是主线程在点击按钮之后并没有进入假死状态,定时器还是在顺利执行,所以 Web Worker 中运行的复杂任务并不会影响主线程的任务调度。

Web Worker 限制

在子线程中运行的代码,无法直接操作 DOM,无法访问 window/document 对象,也无法使用 localStorage 等,如果使用这些 API,代码将会报错:

4

for 循环优化

注意上述代码中的 max 变量,为什么需要一个变量来保存 event.data 值?而不是直接使用 event.data 循环?将 worker.js 改造一下,看看不同使用方式的任务耗时:

// worker.js
self.onmessage = event => {
  console.time('max 循环耗时')
  let n = 0
  let max = event.data
  for (let i = 0; i < max; i++) {
    n += i
  }
  console.timeEnd('max 循环耗时')

  console.time('Object 循环耗时')
  let m = 0
  for (let i = 0; i < event.data; i++) {
    m += i
  }
  console.timeEnd('Object 循环耗时')
  postMessage(n)
}

main.html

// main.html
(() => {
  const worker = new Worker('./worker.js')
  document.getElementById('start').addEventListener('click', () => {
    worker.postMessage(100000000)
  })
})();

执行结果:

5

可以明显看到,性能耗时相差将近 6 倍,这数字会随着对象属性越多,耗时越长!!所以在循环中应当尽量避免读取对象属性,尽可能使用变量来做循环条件!!

写在最后

可以使用 Web Worker 同时启用多个工作线程,只是在任务调度的时候,需要注意响应结果的先后顺序是否对主线程的运行有影响。

一些复杂的计算任务(比如视频转码,图片压缩,图片处理等),都丢给子线程处理吧,咱们前端也可以玩玩多线程~~

 

文章首发于微信公众号【前端路引】,欢迎 微信扫一扫 查看更多文章。

本文来自博客园,作者:前端路引,转载请注明原文链接:https://www.cnblogs.com/linx/p/19069469

 

"Mstar Bin Tool"是一款专门针对Mstar系列芯片开发的固件处理软件,主要用于智能电视及相关电子设备的系统维护与深度定制。该工具包特别标注了"LETV USB SCRIPT"模块,表明其对乐视品牌设备具有兼容性,能够通过USB通信协议执行固件读写操作。作为一款专业的固件编辑器,它允许技术人员对Mstar芯片的底层二进制文件进行解析、修改与重构,从而实现系统功能的调整、性能优化或故障修复。 工具包中的核心组件包括固件编译环境、设备通信脚本、操作界面及技术文档等。其中"letv_usb_script"是一套针对乐视设备的自动化操作程序,可指导用户完成固件烧录全过程。而"mstar_bin"模块则专门处理芯片的二进制数据文件,支持固件版本的升级、降级或个性化定制。工具采用7-Zip压缩格式封装,用户需先使用解压软件提取文件内容。 操作前需确认目标设备采用Mstar芯片架构并具备完好的USB接口。建议预先备份设备原始固件作为恢复保障。通过编辑器修改固件参数时,可调整系统配置、增删功能模块或修复已知缺陷。执行刷机操作时需严格遵循脚本指示的步骤顺序,保持设备供电稳定,避免中断导致硬件损坏。该工具适用于具备嵌式系统知识的开发人员或高级用户,在进行设备定制化开发、系统调试或维护修复时使用。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值