Web Worker 使用教程
作者:@ 很菜的小白在分享
日期:2021年12月8日
概述
JavaScript 语言采用的是单线程,也就是说所有的程序都在这一个线程上执行,之前的代码没有结束后面的就会一直处于等待的状态,使效率较低,安全的同时也存在缺点。
通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。
—— MDN Web Docs
也就是说 Web Worker 会在主线程中创建出一个独立的 Worker 线程,在这个独立的 Worker 中执行不会影响到主线程,当 Worker 执行完毕后会通知到主线程,这样可以使得一些高消耗的程序可以在 Worker 中执行而不会造成程序阻塞,能够合理的利用资源,但如果使用不当也会造成很大的资源浪费,应该在程序执行结束后关闭 Worker。
使用 Web Worker 需遵循以下规则:
- 不可以直接在 worker 中操作 DOM元素
- 无法访问 window 对象,worker 在另外一个全局上下文中运行
DedicatedWorkerGlobalScope
- 在 worker 中可以使用
self
来访问 API - worker 访问的js文件地址必须是
网络文件
,并且需要遵守同源策略
API
主线程
名称 | 说明 |
---|---|
postMessage(msg) | 发送消息,消息类型可由任何类型构成 |
terminate() | 关闭 Worker |
onerror(callback) | Worker 执行错误,通过回调函数捕获错误信息 |
onmessage(callback) | Worker 接收消息,通过回调接收 postMessage 发送的消息 |
onmessageerror(callback) | Worker 消息接收失败,通过回调函数捕获错误信息 |
··· | ··· |
Worker
名称 | 说明 |
---|---|
postMessage(msg) | 发送消息,消息类型可由任何类型构成 |
close() | 关闭当前作用域 (Worker) |
onerror(callback) | Worker 执行错误,通过回调函数捕获错误信息 |
onmessage(callback) | 接收消息,通过回调接收主线程 发送的消息 |
onmessageerror(callback) | 消息接收失败,通过回调函数捕获错误信息 |
dump() | 向控制台写入一条消息 |
importScript() | 向当前 worker 的作用域导入一或更多条脚本。可按需导入任意数量的脚本,使用逗号分割参数。例: importScripts(‘foo.js’, ‘bar.js’); |
··· | ··· |
基本使用
主线程
var worker = new Worker('./web.worker.js');
worker.onmessage(function (event){
// ...
// worker.terminate() // 关闭 worker
})
worker.onmessageerror(function (errMsg){/*...*/})
worker.onerror(function (errMsg){/*...*/})
worker.postMessage({text:'hello World!'}) // 发送消息到 Worker
Worker
self.onmessage(function (event){
let {data} = event
// ...
handle(data)
})
self.onmessageerror(function (err){/*...*/})
function handle(data) {
//...
self.postMessage(data) // 通知消息到主线程
}
实例
Worker 线程完成轮询
需求:需要定时调用接口来查询状态
// 主线程
var worker = new Worker('./web.worker.js');
worker.onmessage(function (event){
let { data } = event
console.log(data)
worker.terminate() // 关闭 worker
})
worker.onmessageerror(function (errMsg){/*...*/})
worker.onerror(function (errMsg){/*...*/})
worker.postMessage({type: 'start'}) // 发送消息到 Worker
// web.worker.js
self.onmessage(function (event){
let {data} = event
if(data.type == 'start'){
handle()
}
})
self.onmessageerror(function (err){/*...*/})
function handle(data) {
let timer = setInterval(function (){
fetch('/getStatus').then(result=>{
if(result.data.status == 'success'){
clearInterval(timer)
self.postMessage(result.data) // 通知消息到主线程
}
})
},1000)
}
(一)Vue 中使用 Web Worker
在 vue 中不可以直接使用 Web Worker,需要安装 worker-loader
加载器来解析
安装依赖
npm install worker-loader -D
配置
// vue.config.js
module.exports = {
chainWebpack: (config) => {
config.module
.rule("worker")
.test(/\.worker\.js$/)
.use("worker")
.loader("worker-loader")
.options({
inline: 'no-fallback',
filename: '[name].worker.js'
})
.end()
}
parallel: false,
}
这里配置的时候需要注意 filename
如果不配置会出现 Worker 文件缓存问题
使用
// web.worker.js
self.onmessage(function (event){
// do something
})
// 组件内
<template>
<div id="app">
// html
</div>
</template>
<script>
import Worker from '@/utils/web.worker.js'
export default {
methods:{
initWorker(){
let worker = new Worker() // 注意此时实例化的就是导入的 Worker 文件
worker.onmessage((event)=>{
// do something
worker.terminate()
})
worker.postMessage({text: 'hello World!'})
}
}
}
</script>
注意
在vue中使用 Web Worker 会出现热更新的问题,作者暂时还没有找到解决方案,具体可以通过每次修改文件名称来重新解析,若您有解决方案,可以私信交流。
(二)Vue 中使用 Web Worker
还有一个也可以实现在 vue 中使用 Web Worker vue-worker
,该库对 Web Worker做了进一步封装使用起来相对方便,可以解决上文中 worker-loader
引起的热更新问题。
安装依赖
npm install vue-worker --save
使用
Git Hub:https://github.com/israelss/vue-worker
具体使用可以参考官方文档,使用基本一致
(完)
若有不妥的地方请私信通知我改正
本文如果对你有所帮助,请留下赞再走吧。