Web Worker
Web Worker 允许你在后台线程中运行 JavaScript 代码,而不会阻塞主线程。这意味着你可以执行复杂的计算或处理大量数据,而不会影响用户界面的响应速度。Web Worker 主要用于以下场景:
- 处理大量数据
- 执行复杂计算
- 处理文件操作
操作
- 生成webworker
new Worker("worker.js")
- 主线程通信
myWorker.postMessage({data:buffer},[buffer]); //这里是大写M,因为这是个函数直接调用,传入参数
myWorker.onmessage = () => {}; //这里是小写的m因为这是个属性名,需要我们挂载内容
- webworker 通信
postMessage() // 在全局对象self上调用 post / onmessage
onMessage
- 关闭webworker
//主线程关闭
myWorker.terminate();
//worker自己关闭
(self.)close()
特性
-
通过 importScripts()导入脚本,生成webworker的时候选择类型classical / modules
-
可以通过结构化克隆或者直接转移数据操作权限(共享内存来实现获取数据)only for Transferable Objects
- postMessage 的第二个参数是需要转交的数据(转交数据后主线程无法访问)
Share Worker
share worker是一种特殊的webworker,api基本于webworker相同,可以认为继承自web worker,
webworker是一个脚本专用的,而share worker是可以被共享的
操作
- 开启share worker
const myWorker = new SharedWorker("worker.js","shareWorker Name")
- 主线程通信
myWorker.port.start() // 如果使用addEventListner,需要手动start
myWorker.port.onmessage = () => {} // 或者👇
myWorker.port.addEventListener('message',()=>{})
myWorker.port.postMessage()
- share worker 通信
onconnet= (e) =>{
const port = e.port[0] // 每一个页面使用一个port
port.onmessage = () => {} //或者👇
port.addEventListener)=>{})
port.postMessage()
port.start() //除非使用addEventlistener,否则是隐式调用的
}
特性
- sharedWorker 是独立于页面的生命周期的,能够在多个页面之间共享内容
- 通过 name或者url 判断是否是同一个 sharedWorker
- chrome://inspect/#workers 可以查看当前shareWorker
- 每一个页面使用一个port ( 需要自己标识 )
Service Worker
Service Worker 是一种特殊类型的 Web Worker,主要用于配合好CacheAPI 控制网络请求和缓存资源。它们在用户访问网站时充当代理服务器,可以拦截网络请求并根据缓存策略返回资源。Service Worker 主要用于以下场景:
- 离线支持
- 缓存管理
- 后台同步
- 推送通知
操作
- 注册 serviceWorkerContainer.register()
- 事件 :intall | activate | message | fetch | sync | push
注册成功后通过监听事件,拦截fetch返回cache中的信息实现细粒度的缓存( 配合Cache API )
特性
- 事件驱动的,不使用的时候会终止
- 使用ES6 Promise
- 需要HTTPS支持
基于Service worker我们甚至可以开发离线应用
Worklet
worklet是浏览器的轻量级后台线程,可以分为paintWorklet , animationWorklet,audioWorklet等
worklet之间也通过消息机制传递信息
// 在主线程中注册 Paint Worklet
if (CSS.paintWorklet) {
CSS.paintWorklet.addModule('path/to/your/paint-worklet.js');
}
// paint-worklet.js
class MyCustomPaint {
static get inputProperties() {
return ['--color'];
}
paint(ctx, geom, properties) {
const color = properties.get('--color').toString();
ctx.fillStyle = color;
ctx.fillRect(0, 0, geom.width, geom.height);
}
}
registerPaint('my-custom-paint', MyCustomPaint);
其他
安全策略
worker具有独立的执行上下文,所以不受限于创建它的 document 的安全策略,worker 的安全策略需要在发送worker 代码的请求本身设置 Content-Security-Policy
结构化克隆算法
浏览器中用于创建副本的算法,主要用于web workers , service workers等
- 他会深度克隆对象属性
- 支持 Date , RegExp, Blob, File, FileList, ArrayBuffer, ArrayBufferView 等
- 循环引用将会报错
- Dom,Function, Error,WeakMap,WeakSet不能被结构化克隆
- 对于复杂,大型的数据接口,性能开销比较大
在worker脚本中使用 ts
ts - js 的转译是webpack等打包工具执行的,直接使用,但是对worker传入ts需要额外的配置
- 编写worker的ts声明文件
declare module "*.worker.ts" {
class WebpackWorker extends Worker {
constructor()
}
}
2. 配置tsconfig.json
{
"compilerOptions":{"lib":["WebWorker"]}
}
3. 以模块的形式导入TS文件并使用无参数实例化
const worker = new Worker()
使用messageChannel通信
除了使用 web worker 提供的方式进行通信(worker.postMessage)
还能够使用 messageChannel 开启通信,这种方式能够在 iframe 之间或者 webworker 之间通信
- 主线程创建 messageChannel
const channel = new messageChannel()
const {port1,port2} = channel // messageChannel实例固定有两个端口
const worker = new Worker('worker.js')
worker.postMessage({port:port1})
- worker中使用
self.onmessage = (e) => {
const {port} = e.data
port.onmessage = ()=>{}
port.postMessage({})
}
部分内容来自网络,侵删 小弟才疏学浅,难免错漏,请各位读者多多担待,不吝赐教。