Web Worker 使用教程

Web Worker 使用教程

作者:@ 很菜的小白在分享
日期:2021年12月8日

概述

JavaScript 语言采用的是单线程,也就是说所有的程序都在这一个线程上执行,之前的代码没有结束后面的就会一直处于等待的状态,使效率较低,安全的同时也存在缺点。

通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。
—— MDN Web Docs

也就是说 Web Worker 会在主线程中创建出一个独立的 Worker 线程,在这个独立的 Worker 中执行不会影响到主线程,当 Worker 执行完毕后会通知到主线程,这样可以使得一些高消耗的程序可以在 Worker 中执行而不会造成程序阻塞,能够合理的利用资源,但如果使用不当也会造成很大的资源浪费,应该在程序执行结束后关闭 Worker。
Web Worker兼容性

使用 Web Worker 需遵循以下规则:

  1. 不可以直接在 worker 中操作 DOM元素
  2. 无法访问 window 对象,worker 在另外一个全局上下文中运行 DedicatedWorkerGlobalScope
  3. 在 worker 中可以使用 self 来访问 API
  4. 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

具体使用可以参考官方文档,使用基本一致

(完)

若有不妥的地方请私信通知我改正
本文如果对你有所帮助,请留下赞再走吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值