Web Worker的使用

为什么要用到worker

因为javascript采用的是单线程模型,也就是所有的任务都只能在一个线程上执行,当解析到一个运算量较大的js的时候,后面的任务只能等前面的js解析完才能进行其他操作。所以就会出现“卡死“的状态。
Web Worker它的作用就是解决以上问题。它可以通过加载一个脚本文件,进而创建一个独立工作的线程,在主线程之外运行。从而营造一个多线程的运行环境,充分利用CPU的资源,减轻主线程的负担。
 

worker中的限制

(1)同源限制
分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
(2)DOM 限制
Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
(3)通信联系
Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
(4)脚本限制
Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
(5)文件限制
Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络
 

线程间通信

postMessage:推送信息
onmessage:接收信息

//Worker线程(test.js)
onmessage = e => {
  console.log(e.data)  // you see you!
  postMessage('one day day!')
}

// 主线程
let w = new Worker('test.js') // 建立Worker
w.postMessage('you see you!')
w.onmessage = e => {
  console.log(e.data)  // one day day!
  w.terminate() // 关闭Worker
}

注意:postMssage只能传递一个参数,传递多个会报错,多个参数建议用Object来传递。
 

关闭Worker

在使用完worker之后,记得及时关闭,节省系统的资源。

// 主线程
worker.terminate();

// Worker 线程
self.close();

 

加载脚本

importScripts('script1.js', 'script2.js')

 

本地文件中使用Web Worker

因为Worker有文件限制,所以要想在本地测试的话有两个方法,
1.通过Blob文件传递worker文件
2.通过服务器访问worker文件(推荐)

通过Blob对象实现Worker

需要将JS的实现代码放到script标签中,然后获取script标签的内容转为Blob对象再建立Worker通信。

  <body>
    <p>Count numbers: <output id="result"></output></p>
    <button onclick="startWorker()">Start Worker</button>
    <script id="getWorker" type="javascript/worker">
      onmessage = e => { 
          console.log(e.data) 
          postMessage('发送的信息') 
      }
    </script>
    <script>
      function test() {
        let workerBlob = new Blob([document.getElementById('getWorker').textContent])
        let w = new Worker(window.URL.createObjectURL(workerBlob))
        w.postMessage('you see you!')
        w.onmessage = e => {
        console.log(e.data)  // one day day!
        w.terminate() // 关闭Worker
        }
      }
    </script>
</body>

 

通过服务器访问worker文件

1.如果你是使用VSCode编译器,直接下载Live Server插件即可
在这里插入图片描述
然后点击Go Live直接跑就可以了,无需转为Blob
在这里插入图片描述
2.可以利用Browsersync同步测试工具
Browsersync官方文档
Browsersync使用教程
 

vue中使用Worker

首先需要安装worker-loader来解析worker文件

npm install worker-loader -D

配置vue.config.js文件

// vue-cli3.0+
module.exports = {
  configureWebpack: config => {
    config.module.rules.push({
      test: /\.worker\.(c|m)?js$/i,
      use: {
        loader: 'worker-loader',
        options: { 
          inline: true,
          publicPath: (pathData, assetInfo) => {
            return `/scripts/${pathData.hash}/workers/`
          }
        }
      }
    })
  }
}

引入文件
引入文件不再是new Worker构建函数了,而是直接实例化该文件!

// test.worker.js
import WorkerFile from './b.js'
let worker = new WorkerFile()

如果worker中使用到window会报错,则需要添加如下配置

chainWebpack: config => {
    config.output.globalObject('this')
 }

打包的时候也会报错,还需添加如下配置

parallel: false

完整版vue.config.js配置

// vue-cli3.0+
module.exports = {
  configureWebpack: config => {
    config.module.rules.push({
      test: /\.worker\.(c|m)?js$/i,
      use: {
        loader: 'worker-loader',
        options: { 
          inline: true,
          publicPath: (pathData, assetInfo) => {
            return `/scripts/${pathData.hash}/workers/`
          }
        }
      }
    })
  },
  parallel: false,
  chainWebpack: config => {
    config.output.globalObject('this')
  }
}

注意:打包后的worker文件没办法实时刷新,即使配置了生成hash也不行,网上说回退到worker-loader2.0.0版本配置options{name: ‘/scripts/workers/WorkerName.[hash].js’}可以,亲测也是不行!暂时只能手动修改文件名来刷新!

 
参考链接
worker文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers
阮一峰教程:http://www.ruanyifeng.com/blog/2018/07/web-worker.html
博客园教程:https://www.cnblogs.com/gerry2019/p/11456035.html
webpack文档:https://github.com/webpack-contrib/worker-loader

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值