JavaScript – Web Worker
前言
在上一篇 << 单线程 与 执行机制 >> 中, 我们提到了 Web Worker.
它的诞生是为了解决 JS 主线程执行耗时计算时, 导致 UI 无法及时更新的卡死现象.
它的解决思路是把同步代码异步化. 原本需要 JS 主线程执行的运算, 转交给另一条线程去完成.
这和 setTimeout 是同一个原理. 计数也不是 JS 主线程做的, 而是定时器触发线程做的.
参考
Worker 基本使用
The Problem
假设我们有一个复杂运算 for loop 50亿次 (耗时 5 秒)
document.querySelector('h1').textContent = 'Hello World';
for (let i = 0; i < 5_000_000_000; i++) {} // 需要 5 秒钟
console.log('do something else');
如果我们让 JS 主线程来处理, 那么 UI 渲染就会慢 5 秒钟, 用户迟迟才会看见 Hello World 出现.
New Web Worker
这时我们可以开启 Web Worker, 它会创建另一条线程去处理这个 for loop. 然后我们把后续的代码变成一个 callback.
worker.js
for (let i = 0; i < 5_000_000_000; i++) {} // 需要 5 秒钟
self.postMessage('done'); // 通知主线程, 任务完成
self.close(); // 可以在子线程关闭, 也可以交由主线程关闭.
index.js
document.querySelector('h1').textContent = 'Hello World';
const worker = new Worker('./worker.js', { name: 'worker' });
// callback
worker.addEventListener('message', () => {
console.log('do something else');
worker.terminate(); // 关闭子线程
});
通过 addEventListener 注册 callback, 这样原本同步的代码就变成异步了.
Worker 沟通
主线程和子线程 (worker) 的沟通是通过 postMessage 和 addEventListener('message') 完成的.
postMessage 类似于 dispatchEvent 的意思.
主线程和子线程都可以 postMessage 和 listen message, 也都可以关闭子线程.
主线程也能监听子线程的错误
// index.ts – main thread
worker.postMessage('message'); // dispatch event to child thread
worker.addEventListener('message', () => {}); // listen event from child thread
worker.addEventListener('error', () => {}); // listen error from child thread
worker.terminate(); // close child thread // worker.ts – child thread
self.postMessage('done'); // dispatch event to main thread
self.addEventListener('message', () => {}); // listen event from main thread
self.close(); // close child thread (把自己关了)
Message Data Type
// index.ts
const worker = new Worker('./worker.js', { name: 'worker' });
const file = document.querySelector('input').files[0];
file.arrayBuffer().then(arrayBuffer => {
worker.postMessage({ value: 'value', buffer: arrayBuffer }, { transfer: [arrayBuffer] });
}); // worker.ts
self.addEventListener('message', event => {
const { value, buffer } = event.data;
});
两个点要注意
1. postMessage 可以传对象, 但是对象会被 deep copy.
2. ArrayBuffer 也会被 copy, 有时候 size 太大 copy 会很慢, 所以 postMessage 有个设置叫 transferable objects
声明 transfer 以后, ArrayBuffer 就转交给 worker 了 (no more copy, use cut instead), 这时主线程就不可以再读取 ArrayBuffer了.
Import Script in Worker
self.importScripts('/imported-script.js');
worker 内可以 import 其它的 script.
imported-script.js 也可以调用 self.postMessage 和主线程沟通.
而 worker 和 imported-script 要沟通则是通过全局变量 e.g. self.value = 'some value'.
SharedWorker
目前支持率不是很好, 以后才研究 TODO...
JavaScript – Web Worker的更多相关文章
- 深入理解javascript异步编程障眼法&&h5 web worker实现多线程
0.从一道题说起 var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert('end'); 1 2 3 4 ...
- JavaScript多线程之HTML5 Web Worker
在博主的前些文章Promise的前世今生和妙用技巧和JavaScript单线程和浏览器事件循环简述中都曾提到了HTML5 Web Worker这一个概念.在JavaScript单线程和浏览器事件循环简 ...
- Web Worker javascript多线程编程(一)
什么是Web Worker? web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验. 一般来说Javascript ...
- Web Worker javascript多线程编程(二)
Web Worker javascript多线程编程(一)中提到有两种Web Worker:专用线程dedicated web worker,以及共享线程shared web worker.不过主要讲 ...
- javascript 多线程Web Worker不引用外部js文件的方法
最近在Android开发中 Webview通过调用JavascriptInterface的方式与App交互 在交互的过程中,有些App上的操作时间会比较长,Web中调用的话会造成程序假死的情况 于是想 ...
- 【转向Javascript系列】深入理解Web Worker
本文首发在alloyteam团队博客,链接地址http://www.alloyteam.com/2015/11/deep-in-web-worker/ 上一篇文章<从setTimeout说事件循 ...
- 【转】Web Worker javascript多线程编程(一)
原文:https://www.cnblogs.com/peakleo/p/6218823.html -------------------------------------------------- ...
- 过段时间逐步使用HTML5新增的web worker等内容
想来快2017年了,2013年前的手机应该很少有人用了,以后逐渐使用HTML5新增的高级API吧. 先把web worker的内容再熟悉一下,因为微软虚拟学院的'面向有经验开发人员的 JavaScri ...
- web Worker使js实现‘多线程’?
大家都知道js是单线程的,在上一段js执行结束之前,后面的js绝对不会执行,那么为什么标题说js实现‘多线程’,虽然说加了引号,可是标题也不能乱写不是,可恶的标题党? 姑且抛开标题不说,先说我们经常会 ...
- HTML5:web socket 和 web worker
a:hover { cursor: pointer } 做练习遇到了一个选择题,是关于web worker的,问web worker会不会影响页面性能?补习功课之后,答案是不会影响. 查阅了相关资料学 ...
随机推荐
- 解决方案 | Claunch 如何更新配置文件
1.问题 比如我的电脑上有Claunch 3.26版本(绿色版本),但是更新的时候如何保证我的新版本的图标.链接也更新是个问题. 官网说得比较模糊: 2.解决方法 打开复制data数据覆盖到新版本同样 ...
- ComfyUI进阶:Comfyroll插件 (一)
ComfyUI进阶:Comfyroll插件 (一) 前言: 学习ComfyUI是一场持久战,而Comfyroll Studio 是一款功能强大的自定义节点集合,专为 ComfyUI 用户打造,旨在提供 ...
- vue 理解yarn start 和yarn dev的区别
yarn dev,当文件变动后,会自动重启. yanr start不会自动重启 nodemon会监听文件变动,跟yarn dev和yarn start无关.
- [rCore学习笔记 06]运行Lib-OS
QEMU运行第一章代码 切换分支 git checkout ch1 detail git checkout ch1 命令是用来切换到名为 ch1 的分支或者恢复工作目录中的文件到 ch1 提交的状态 ...
- .NET Core 3.x 基于AspectCore实现AOP,实现事务、缓存拦截器
最近想给我的框架加一种功能,就是比如给一个方法加一个事务的特性Attribute,那这个方法就会启用事务处理.给一个方法加一个缓存特性,那这个方法就会进行缓存.这个也是网上说的面向切面编程AOP. A ...
- ABC361
A link 先输出前\(k\)个,再输出\(x\),最后输出后面的. 点击查看代码 #include<bits/stdc++.h> using namespace std; int n, ...
- 《Programming from the Ground Up》阅读笔记:p88-p94
<Programming from the Ground Up>学习第5天,p88-p94总结,总计7页. 一.技术总结 1.touppercase.s #PURPOSE: This pr ...
- mybatis:映射方式与SQL注入
1.映射方式有两种,一种是resultType 这个是有一个实体类其成员与数据库中表字段一一对应,下例中就是User类对应了user表 <mapper namespace="com.e ...
- cgroup限制进程cpu
编写一个死循环脚本 [root@workstation ~]# cat circle.sh #!/bin/bash a=1 while true do let a++ done 查看top 使用cgr ...
- 【Server】对象存储OSS - Minio
官方文档: https://docs.min.io/docs/minio-quickstart-guide.html 看中文文档CV命令发现下不下来安装包,应该是地址问题 单击搭建非常简单,只有三个步 ...