JS异步编程——WebWorker多线程机制
·
文章目录
前言
JS采用的是单线程机制,所有的任务只能在一个线程上完成,前面的任务没有完成就只能等待。随着计算机计算能力的增强,多核处理器的出现,单线程已不能充分的发挥计算机的算力,WebWorker就是给主线程创建多线程的环境,实现主线程运行时,WebWorker线程在后台运行,两者互不干扰,待WebWorker线程任务完成后,将结果返回给主线程。
一、WebWorker多线程机制

1. worker发展历史

worker在2009年就提出了草案,到2012年的时候,主流浏览器就已经全面的支持worker了。

worker的规范有两个,分别是DedicatedWorker和SharedWorker。SharedWorker浏览器的兼容性问题较大,基本不使用,现在大家普遍所讲的worker都是遵从DedicatedWorker规范。

从图中可以看到,SharedWorker的兼容性一路标红。
// 创建DedicatedWorker
const worker = new Worker("worker.js");
// 创建SharedWorker
var myWorker = new SharedWorker("worker.js");
2. 主线程和多线程
主线程

单线程中,JS阻塞用户交互和页面渲染

多线程

3. 什么时候使用worker
1.减少卡顿可使用
根据Chrome团队提出的用户感知性能模型RAIL,同步JS执行时间不能过长。量化来说,播放动画时建议小于16ms,用户操作响应建议小于100ms,页面打开到开始呈现内容建议小于1000ms。
2.worker只有在多核处理器上,才有可能性能提升
进程是操作系统资源分配的基本单位,线程是操作系统调度CPU的基本单位。操作系统对线程能占用的CPU计算资源有复杂的分配策略。
单核多线程通过时间切片交替执行。这是使用worker,可能会由于线程间的通信导致执行所花费时间的总时长更久。
多核多进程可在不同核中真正并行。此时使用worker才能提高性能。

通信消耗(所提升的性能 = 并行执行所节省的时间 - 通信消耗的时间)

4. worker API

// main.js
const worker = new Worker('./worker.js);
worker.postMessage('hello');
worker.onmessage = (event) => {
console.log(event.data); //world
}
// worker.js
self.onmessage = (event) => {
console.log(event.data); //hello
poatMessage('world');
}
5. JS主线程和Worker线程的相同点和不同点
1.运行环境

2.相同点
1.包含完整的JS运行时(JS运行时有两个阶段:编译阶段和执行阶段),支持ECMAScript规范定义的语言语法和内置对象。
JS运行时的详细介绍:https://www.jianshu.com/p/672d512fdbae
2.支持XmlHttpRequest,能独立发送网络请求与后台交互。
3.包含只读的Location,指向Worker线程执行的script url,可通过url传递参数给Worker环境。
4.包含只读的Navigator,用于获取浏览器信息,如通过Navigator.userAgent识别浏览器。
5.支持setTimeout/setinterval计时器,可用于实现异步逻辑。
6.支持WebSocket进行网络I/O;支持IndexedDB进行文件I/O。
3.不同点
1.Worker线程没有DOM API,无法新建和操作DOM;也无法访问到主线程的DOM Element。
2.Worker线程和主线程间内存独立,Worker线程无法访问页面上的全局变量(window,document等)和JavaScript函数。
3.Worker线程不能调用alert()或confirm()等UI相关的BOM API。
4.Worker线程被主线程控制,主线程可以新建和销毁Worker。
5.Worker线程可以通过self.close自行销毁。
6. 浏览器的16ms渲染帧
日常使用屏幕的刷新频率是60HZ(也就是1秒钟更新60幅图像,1000/60 ~= 16ms)。
根据谷歌引擎为例分析结论:
1. 一个渲染帧内commit的多次DOM改动会被合并渲染。
2. 好事JS会造成丢帧。
3. 渲染帧间隔为16ms左右。
4. 避免耗时脚本、交错读写样式以保证流畅的渲染。
渲染帧流程:
1. 脚本执行(JavaScript):脚本造成了需要重绘的改动,比如增删DOM、请求动画等。
2. DOM树构建/样式计算(CSS Object Model):级联地生成每个节点的生效样式。
3. 布局(Layout):计算布局,执行渲染算法。
4. 重绘(Paint):各层分别进行绘制(比如3D动画)。
5. 合成(Composite):合成各层的渲染结果。
执行队列

优化
耗时超过16ms的JavaScipt可能会丢帧让页面变卡。如果有太多事情要做可以把这些工作重新设计,分割到各个阶段中执行。并充分利用缓存和懒初始化等策略。
不同执行时机的JavaScript有不同的优化方式。
1. 服务器端渲染或者应用懒初始化策略。
2. 耗时脚本可以优化算法或者迁移到Worker中。
总结
革命尚未成功,同志仍需努力。
更多推荐



所有评论(0)