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会不会影响页面性能?补习功课之后,答案是不会影响. 查阅了相关资料学 ...
随机推荐
- webpack4.15.1 学习笔记(八) — 缓存(Caching)
目录 输出文件名(Output Filenames) 缓存第三方库 将 js 文件放到一个文件夹中 webpack 打包模块化后的应用程序,会生成一个可部署的 /dist目录,只要 /dist 目录中 ...
- [oeasy]python001_先跑起来_python_三大系统选择_windows_mac_linux
先跑起来 Python 什么是 Python? Python [ˈpaɪθɑ:n] 是 一门 适合初学者 的编程语言 添加图片注释,不超过 140 字(可选) 类库 众多 几行代码 就 ...
- [oeasy]python0074_修改字体背景颜色_background_color_背景色
修改背景色 回忆上次内容 上次将asciiart和颜色一起来玩 7 种基本色 变化多端 不过到目前为止 改的 都是前景色 背景色可以修改吗? 重温参数 具体动手试试 print("\033[ ...
- [oeasy]python0067_ESC键进化历史_键盘演化过程_ANSI_控制序列_转义序列_CSI
光标位置 回忆上次内容 上次了解了 新的转义模式 \33 逃逸控制字符 esc 这个字符让输出退出标准输出流 进行控制信息的设置 可以设置光标输出的位置 ASR33中的ALT MODE 是 今天的ES ...
- C#:进程之间传递数据
一.思路 在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.常用的方法有 使用内存映射文件 通过共享内存DLL共享内存 使用SendMessage向另一进程发送WM_COPYDATA ...
- 题解:CF1971D Binary Cut
题解:CF1971D Binary Cut 题意 给予你一个 \(01\) 字符串,你可以将它分割,分割后必须排成先 \(0\) 后 \(1\) 的格式. 求最少分割为几部分. 思路 将 \(0\) ...
- selenium启动Chrome配置参数问题
每次当selenium启动chrome浏览器的时候,chrome浏览器很干净,没有插件.没有收藏.没有历史记录,这是因为selenium在启动chrome时为了保证最快的运行效率,启动了一个裸浏览器, ...
- CMake学习(一)
CMake学习(一) 1.简介 CMake是一个强大的软件构建系统,可以用简单的语句来描述所有平台的安装(编译过程) 可以编译源代码.制作程序库.产生适配器(wrapper).还可以用任意的顺序建构执 ...
- 【TypeScript】02 面向对象
[联合类型] 联合类型(Union Types)可以通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值. 注意:只能赋值指定的类型,如果赋值其它类型就会报错. var val:strin ...
- ViT:拉开Trasnformer在图像领域正式挑战CNN的序幕 | ICLR 2021 —— An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale
论文地址: https://arxiv.org/abs/2010.11929 Github地址: https://github.com/google-research/vision_transform ...