前言

在上一篇 << 单线程 与 执行机制 >> 中, 我们提到了 Web Worker.

它的诞生是为了解决 JS 主线程执行耗时计算时, 导致 UI 无法及时更新的卡死现象.

它的解决思路是把同步代码异步化. 原本需要 JS 主线程执行的运算, 转交给另一条线程去完成.

这和 setTimeout 是同一个原理. 计数也不是 JS 主线程做的, 而是定时器触发线程做的.

参考

阮一峰 – Web Worker 使用教程

MDN – SharedWorker

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的更多相关文章

  1. 深入理解javascript异步编程障眼法&&h5 web worker实现多线程

    0.从一道题说起 var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert('end'); 1 2 3 4 ...

  2. JavaScript多线程之HTML5 Web Worker

    在博主的前些文章Promise的前世今生和妙用技巧和JavaScript单线程和浏览器事件循环简述中都曾提到了HTML5 Web Worker这一个概念.在JavaScript单线程和浏览器事件循环简 ...

  3. Web Worker javascript多线程编程(一)

    什么是Web Worker? web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验. 一般来说Javascript ...

  4. Web Worker javascript多线程编程(二)

    Web Worker javascript多线程编程(一)中提到有两种Web Worker:专用线程dedicated web worker,以及共享线程shared web worker.不过主要讲 ...

  5. javascript 多线程Web Worker不引用外部js文件的方法

    最近在Android开发中 Webview通过调用JavascriptInterface的方式与App交互 在交互的过程中,有些App上的操作时间会比较长,Web中调用的话会造成程序假死的情况 于是想 ...

  6. 【转向Javascript系列】深入理解Web Worker

    本文首发在alloyteam团队博客,链接地址http://www.alloyteam.com/2015/11/deep-in-web-worker/ 上一篇文章<从setTimeout说事件循 ...

  7. 【转】Web Worker javascript多线程编程(一)

    原文:https://www.cnblogs.com/peakleo/p/6218823.html -------------------------------------------------- ...

  8. 过段时间逐步使用HTML5新增的web worker等内容

    想来快2017年了,2013年前的手机应该很少有人用了,以后逐渐使用HTML5新增的高级API吧. 先把web worker的内容再熟悉一下,因为微软虚拟学院的'面向有经验开发人员的 JavaScri ...

  9. web Worker使js实现‘多线程’?

    大家都知道js是单线程的,在上一段js执行结束之前,后面的js绝对不会执行,那么为什么标题说js实现‘多线程’,虽然说加了引号,可是标题也不能乱写不是,可恶的标题党? 姑且抛开标题不说,先说我们经常会 ...

  10. HTML5:web socket 和 web worker

    a:hover { cursor: pointer } 做练习遇到了一个选择题,是关于web worker的,问web worker会不会影响页面性能?补习功课之后,答案是不会影响. 查阅了相关资料学 ...

随机推荐

  1. 「Pygors跨平台GUI」1:Pygors跨平台GUI应用研究

    「Pygors系列」一句话导读: Python.Go.Rust.C程序跨平台GUI框架研究. 一.问题 Pygors是什么? Pygors是我自己创造的一个词,就是Python.Go.Rust.C四种 ...

  2. 要想业务中台建得快,最好用Service Mesh来带

    中国企业数字化转型进入深水区,业务中台及下一代微服务Service Mesh(服务网格)被越来越多的人关注,本文结合网易轻舟微服务Service Mesh实践,解析业务中台为什么需要Service M ...

  3. 机器学习策略篇:详解处理数据不匹配问题(Addressing data mismatch)

    处理数据不匹配问题 如果您的训练集来自和开发测试集不同的分布,如果错误分析显示有一个数据不匹配的问题该怎么办?这个问题没有完全系统的解决方案,但可以看看一些可以尝试的事情.如果发现有严重的数据不匹配问 ...

  4. ProgressBar 进度控件

    在 VB.NET 中,你可以使用 ProgressBar 控件或者自定义的进度提示方法来实现这个功能.以下是一个示例代码,展示如何使用 ProgressBar 控件来显示导入情况: ' 创建一个 Pr ...

  5. 适用于 .NET 的现代化、流畅、可测试的HTTP客户端库

    前言 今天大姚给大家分享一个.NET开源(MIT License).免费.现代化.流畅.可测试.可移植的URL构建器和HTTP客户端库:Flurl. 项目介绍 Flurl是一个集现代性.流畅性.异步性 ...

  6. Django template层之json报文遍历总结

    Django template层之json报文遍历总结 by:授客 QQ:1033553122 测试环境 Win7 Django 1.11 实例 Views.py def home(request): ...

  7. 2023年最新ios证书申请流程

    做过前端多端开发的朋友们都知道,hbuilderx或apicloud这些开发工具的uniapp框架可以开发ios应用,使用他们的云打包即可. 云打包的时候需要一个私钥证书和一个profile文件,这两 ...

  8. 映射lun

    环境 VMware1 网卡与 主机ping通 创建文件夹将文件解压进去 删除压缩包 创建虚拟机 下一步下一步,完成虚拟机 编辑虚拟机设置 否 账号密码 admin Admin@storage 等待 导 ...

  9. 【Java】Applet开发

    一.Applet开发环境准备 IDEA在2018版本默认提供了Applet启动配置 创建一个Applet应用配置: 在IDEA2019版本之后,这个应用配置选项被移除了,改为Java Applet S ...

  10. 【Vue】06 Webpack Part2 打包命令配置

    Webpack 配置: 入口 & 出口: 就是我们使用的打包命令: 一个是对什么文件执行,这就是入口 一个是输出到什么文件,这就是出口 每一次打包使用这个命令都必须指定这两个必要的参数 所以将 ...