详解 WebWorker 的概念、使用场景、示例

前言

提到 WebWorker,可能有些小伙伴比较陌生,不知道是做什么的,甚至不知道使用场景,今天这篇文章就带大家一起简单了解一下什么是 webworker!

概念

WebWorker 实际上是运行在浏览器后台的一个单独的线程,因此可以执行一些耗时的操作而不会阻塞主线程。WebWorker 通过与主线程之间传递消息实现通信,这种通信是双向的。WebWorker不能直接访问 DOM,也不能使用像 window 对象这样的浏览器接口对象,但可以使用一些WebWorker 标准接口和 Navigator 对象的部分属性和方法。

为什么使用WebWorker?

  1. 提高应用响应能力:主线程被独占执行一些耗时的计算或操作时,会导致UI无响应。WebWorker 可以把这些任务转移到后台线程,从而保证主线程的运行,提高应用的响应能力。
  2. 充分利用多核CPU:现代CPU都是多核的,WebWorker 可以让 Web 应用利用多核 CPU 的并行计算能力,充分发挥计算机硬件性能。
  3. 避免渲染阻塞:JavaScript 运行在主线程,如果主线程一直占用,就无法执行 GUI 渲染任务,导致界面渲染受阻。WebWorker 把一些费时任务分流到后台线程就可以避免这一问题。
  4. 后台持续运行:WebWorker 所在后台线程可持续运行,即使页面被挂起或最小化,任务仍在后台执行,非常适合一些需要长时间运行的操作。

使用场景

一般来说,当遇到如下几种情况时可以考虑使用 WebWorker:

  1. 大量数据的计算/处理:比如图像处理、数据分析等
  2. 长时间运行的操作:如一些复杂的数学计算
  3. 非阻塞式操作:希望执行一些耗时操作时不阻塞主线程

示例

假设我们有一个需要计算斐波那契数列的任务,我们可以使用 Web Worker 来进行计算,以避免阻塞主线程。以下是一个简单的示例:

主线程

主线程创建 worker 实例,向子线程通过 postMessage 发送消息,通过 onmessage 监听子线程返回的数据。

  const myWorker = new Worker('./worker.js')

  myWorker.onmessage = function (e) {
    console.log('Fibonacci result:', e.data)
  }

  myWorker.postMessage(40) // 请求计算斐波那契数列的第40项

worker.js

在同级目录下创建 worker.js文件,通过 onmessage 接收主线程发来的数据,计算后通过postMessage 将计算结果返回主线程。

self.onmessage = function (e) {
  const n = e.data
  let a = 0,
    b = 1,
    temp
  for (let i = 2; i <= n; i++) {
    temp = a
    a = b
    b = temp + b
  }
  self.postMessage(b)
}

运行结果

可以看到主线程打印出 webworker 计算的运行结果

Vue、React项目使用

接下来为大家演示 vue 以及 react 项目如何使用

Vue使用

vue版本:"vue": "^2.6.14",vue-cli版本:@vue/cli 5.0.8安装 worker-loader

页面使用

<template><div>我的页面</div></template>
<script>
export default {
  name: 'MyselfView',
  data() {
    return {
      worker: null,
    }
  },
  mounted() {
    // 创建 WebWorker 实例
   this.worker = new Worker(new URL('./worker.js', import.meta.url))
    console.log('worker: ', this.worker)
    this.worker.postMessage(40) // 请求计算斐波那契数列的第40项

    this.worker.addEventListener('message', (event) => {
      console.log('Fibonacci result:', event.data)
    })
  },
  beforeDestroy() {
    // 组件销毁时终止 WebWorker
    this.worker.terminate()
  },
}
</script>

worker.js

// worker.js
self.addEventListener('message', (e) => {
  console.log('e: ', e)
  const n = e.data
  let a = 0,
    b = 1,
    temp
  for (let i = 2; i <= n; i++) {
    temp = a
    a = b
    b = temp + b
  }
  self.postMessage(b)
})

效果 

React使用 

react版本: "react": "^18.2.0"

import React, { useEffect } from 'react'
// import WorkerScript from './worker.worker.js'

const Demo = () => {
  useEffect(() => {
    const worker = new Worker(new URL('./worker.worker.js', import.meta.url))

    worker.onmessage = function (e) {
      console.log('Fibonacci result:', e.data)
    }
    worker.postMessage(40) // 请求计算斐波那契数列的第40项
    // 使用 worker ...
    return () => worker.terminate()
  }, [])

  return (
    <div>
      <p>count的值</p>
    </div>
  )

效果

注意

由于我们在项目开发时,使用不同的打包工具(vite/webpack)。幸运的是,最新版的vite/webpack都支持Web Worker了。

我们可以通过:new URL()的方式 --vite/webpack都支持

new Worker(
  new URL(
    './worker.js', 
    import.meta.url
  )
);

总结

WebWorker是一种在 Web 应用中实现多线程运行的技术,可以将耗费 CPU 的任务交给后台线程处理,避免阻塞主线程,从而提高Web应用的响应性能和用户体验。 总之,WebWorker的引入解决了Web应用长期以来在单个线程中运行所带来的诸多问题,有效提升了Web应用的运行性能和用户体验。

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ThreadLocal 是 Java 中的一个线程局部变量,它为每个线程提供了独立的变量副本,每个线程都可以通过 ThreadLocal 对象来访问自己的变量副本,而不会影响其他线程的副本。ThreadLocal 在多线程编程中非常有用,可以解决线程安全问题。 使用 ThreadLocal 的主要场景包括: 1. 线程上下文信息传递:有些情况下,我们需要在多个方法之间传递一些上下文信息,例如用户认证信息、数据库连接等。使用 ThreadLocal 可以避免在方法参数中传递这些上下文信息,每个线程都可以独立地访问自己的上下文信息。 2. 线程安全的对象:有些对象在多线程环境下是不安全的,如果每个线程都持有一个对象的副本,就可以避免多线程竞争访问导致的安全问题。例如 SimpleDateFormat 是非线程安全的,可以使用 ThreadLocal 来为每个线程提供一个独立的 SimpleDateFormat 对象。 3. 隐式参数传递:有些方法需要依赖某些参数,但是这些参数对于调用方来说并不是必须的。使用 ThreadLocal 可以将这些参数设置为 ThreadLocal 变量,在方法中直接获取这些参数,而不需要显式传递。 需要注意的是,使用 ThreadLocal 时要及时清理资源,避免内存泄漏。在使用完毕后,应该调用 ThreadLocal 的 remove() 方法来清理当前线程持有的变量副本。 总之,ThreadLocal 可以用于在多线程环境下实现线程安全、线程间数据隔离和传递上下文信息等功能。但是过度使用 ThreadLocal 也会导致代码可读性变差,增加了代码的复杂性,需要根据具体场景进行合理使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JacksonChen_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值