webWorker 介绍

Web Worker 是一种在浏览器后台运行脚本的技术,它允许你在不影响页面性能和响应速度的情况下执行复杂的计算任务。通过 Web Worker,你可以创建一个或多个后台线程来处理耗时的操作,如数据处理、图像操作、网络请求等,而不会阻塞主执行线程(即负责渲染页面和响应用户交互的线程)。

webWorker 主要分三种
  1. Dedicated Worker (常用的webWorker)
  2. shareWorker (用于跨标签页信息数据同步分享)
  3. serviceWorker (用于离线缓存等功能)
Dedicated Worker

常用的webWorker,常用于处理cpu密集型任务(hash加密,计算,解密)

// worker.js 计算斐波那契数列 
self.onmessage = function (e) {
	const num = e.data

	let result = fibonacciMemoization(Number(num))
	self.postMessage(result)
}
function fibonacciMemoization(n, memo = {}) {
	if (n in memo) return memo[n]
	if (n <= 1) return n
	memo[n] = fibonacciMemoization(n - 1, memo) + fibonacciMemoization(n - 2, memo)
	return memo[n]
}
self.onerror = function (e) {
	console.error(e)
	self.postMessage({
		error: e.message,
	})
}

// home.vue
<template>
	<div class="about">
		<input type="number" v-model="num" />
		<button @click="handleSum">开始计算斐波那契数列</button>
	</div>
</template>
<script setup>
import {ref, onMounted, onUnmounted} from 'vue'
let worker = new Worker(new URL('../worker/fibonacciWorker.js', import.meta.url))
let num = ref(0)
let handleSum = () => {
	worker.postMessage(num.value)
	worker.onmessage = (e) => {
		console.log(e.data)
	}
}
// 页面组件卸载时关闭worker
onUnmounted(() => {
  if(worker){
  	worker.terminate()
  	worker = null
  }

})
</script>
SharedWorker

SharedWorker 是一种在浏览器中允许多个浏览上下文(如同一浏览器内的不同窗口、标签页或 iframe)之间共享的后台工作线程。与 Web Worker 不同,后者为每个创建它的脚本提供了一个独立的工作线程,而 SharedWorker 可以被同一应用中的多个页面实例访问。

// shared-worker.js

// 存储所有的端口以便广播消息
let connections = []

self.onconnect = function (e) {
	const port = e.ports[0]
	console.log('connect', port)

	// 当有新的连接时,将其添加到列表中
	connections.push(port)

	// 每当接收到消息时,广播给所有其他连接
	port.onmessage = function (e) {
		for (let i = 0; i < connections.length; i++) {
			if (connections[i] !== port) {
				// 不要发送回原发者
				connections[i].postMessage(e.data)
				connections[i].start()
			}
		}
	}
}

简单封装shareWorker的使用

// useSharedWorker.js
export default class useSharedWorker {
	constructor(url) {
		this.url = url
		this.connected = false
		this.worker = null
	}
	init(callback) {
		this.worker = new SharedWorker(this.url)
		console.log('init', this.worker)
		if (this.worker.port) {
			this.connected = true
			this.worker.port.onmessage = (e) => {
				callback(e.data)
			}
		}
	}
	postMessage(data) {
		if (!this.connected && !this.worker) return
		this.worker.port.start()
		this.worker.port.postMessage(data)
	}
	closeWorker() {
		if (this.worker) {
			this.worker.port.close()
		}
	}
}

使用栗子

// Home.vue
<template>
	<div>
		<button @click="handleShare">分享</button>
	</div>
</template>
<script setup>
import {ref, onUnmounted, onMounted} from 'vue'
// 上面封装的useShareWork.js
import useSharedWorker from '@/components/useShareWork'
let shareWork = new useSharedWorker(new URL('../worker/shareWorker.js', import.meta.url))
onMounted(() => {
	shareWork.init((res) => {
		console.log('Home接收到的消息', res)
	})
})
let handleShare = () => {
	shareWork.postMessage(JSON.stringify({name: 'home', age: 18}))
}
onUnmounted(() => {
	shareWork.closeWorker()
})
</script>

// About.vue
<template>
	<div class="about">
		<div>about 页面</div>
		<button @click="handleShare">about 分享</button>
	</div>
</template>
<script setup>
import {ref, onMounted, onUnmounted} from 'vue'

import useSharedWorker from '@/components/useShareWork'

let shareWork = new useSharedWorker(new URL('../worker/shareWorker.js', import.meta.url))
onMounted(() => {
	shareWork.init((res) => {
		console.log('About接收到的消息', res)
	})
})

let handleShare = () => {
	shareWork.postMessage('来自about页面的消息')
}
onUnmounted(() => {
	
	shareWork.closeWorker()
})
</script>
<style>
@media (min-width: 1024px) {
	.about {
		min-height: 100vh;
		display: flex;
		align-items: center;
	}
}
</style>
// Aside.vue
<template>
	<div class="about">
		<div>aside页面</div>
		<h1>{{ title }}</h1>
		<button @click="handleShare">aside 分享</button>
	</div>
</template>
<script setup>
import useSharedWorker from '@/components/useShareWork'
import {ref, onUnmounted} from 'vue'
let title = ref()
let shareWork = new useSharedWorker(new URL('../worker/shareWorker.js', import.meta.url))
shareWork.init((res) => {
	console.log('aside接收到的消息', res)
	title.value = res
})
let handleShare = () => {
	shareWork.postMessage('来自aside页面分享的消息')
}
onUnmounted(() => {
	shareWork.closeWorker()
})
</script>

效果截图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

serviceWorker

主要用于离线缓存,具体可以参考pwa实现方式
PWA 文档地址 Vite-pwa

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐