共计 2428 个字符,预计需要花费 7 分钟才能阅读完成。
前言
大家好,我是林三心,用最通俗易懂的话讲最难的知识点 是我的座右铭,根底是进阶的前提 是我的初心,明天给大家讲一个你们既相熟又生疏的货色——Web Worker
为什么 js 是单线程语言?
先给大家说说 JavaScript 为啥是一个单线程语言呢?咱们都晓得,JavaScript 是一门以前端为主的语言,而前端的舞台就是浏览器,而浏览器通过什么取悦用户呢?通过的是一个一个的 DOM 节点组成的页面。所以说,JavaScript 最终的目标都要以页面展示的品质为目标。
而 JavaScript 设计为单线程语言也是为了页面,咱们假如 JavaScript 是多线程语言,如果有一天,线程 1 在批改 DOM 节点,同时线程 2 也在批改同一个 DOM 节点,那请问页面应该听谁的?这就会造成抵触,而这在用户背后可是不被容许的,所以 JavaScript 设计成了单线程语言,想要操作啥,都得按着程序来。
Web Worker?
背景
刚刚也说了 JavaScript 是单线程语言,这也造成了许多问题。不晓得大家平时开发的时候,有没有遇到这样的事:解决一个超级大的数据,导致整个代码的逻辑被阻塞了一段时间
说说我遇到的场景吧:
- 1、大文件切片上传配 hash 时,需解决一小段时间
- 2、树形数据前端解决时,须要解决一小段时间
而这可能导致了什么假死
问题呢? - 1、页面渲染的阻塞
- 2、前面代码执行的阻塞
是什么?
Web Worker
为了解决浏览器 假死
这个问题而孕育而生的一项新技术。它是多线程模型,也是基于宿主。它属于 JavaScript 线程中的一个子线程,它齐全受主线程管制,然而在 Web Worker
外面是不能操作 DOM 的。须要保障 DOM 的唯一性,因而主的基调不能扭转,然而须要有一个新的线程来分担繁冗的计算工作,这个也就是 Web Worker
兼容性:
Web Worker
有以下特点:
- 1、一旦新建,则不会被主线程打断。即使是主线程卡死,Web Worker 依然运行中
- 2、Web Worker 也受同源策略限度,同源网页能力拜访
- 3、不能操作和拜访 DOM,后面也说了多线程操作 DOM 容易造成抵触,所以禁止
- 4、不能应用全局交互办法(alert、confirm 等),其余全局办法根本能够应用
- 5、不能读取本地文件(其实浏览器自身就禁止 JavaScript 读取本地文件,出于平安思考)
- 6、worker 线程与主线程不共享作用域与资源
-
7、Web Worker 有两种:
Dedicated Web Worker
:专用线程,只能在一个网页里应用这个线程Shared Web Worker
:共享线程,能够在多个同源的网页中共享,也是跨页面通信的伎俩之一
应用 Web Worker
场景
为了让大家看到 Web Worker
的成果,我新建了几个文件
// index.html
<script src="./index.js"></script>
<img src="./ 头像.jpg" alt="">
// index.js
console.time('解决数据工夫')
// 模仿数据处理
function handleData(num) {for (let i = 0; i < num; i++) {
let str = ''
while (str.length < 150) {str += '哈'}
}
}
handleData(2000000)
console.timeEnd('解决数据工夫')
咱们能够看看解决数据花了多少工夫:
而图片的渲染也是在这个工夫之后(渲染图片也须要肯定工夫,所以有差值),这也阐明了刚刚的数据处理,阻塞了页面的渲染:
Web Worker 根本应用
我的项目开发中用 Dedicated Web Worker
,比拟多,所以讲讲这个的根本应用吧
改写一下 index.js
中的代码
// index.js
// 实例一个 Woeker,并传入指标文件门路,这个指标文件将会生成一个 worker 线程
const worker = new Worker("data.js")
// 应用 postMessage 传输信息到指标文件
worker.postMessage(2000000)
// 应用 onmessage 承受信息
worker.onmessage = (e) => {console.log(e.data)
};
// 应用 onerror 进行指标文件,也就是指定 worker 线程产生谬误时的回调
worker.onerror = function (e) {console.log("error at" + e.filename + ":" + e.lineno + e.message)
};
而后咱们创立一下指标文件 data.js
,他将会生成一个 worker 线程
// 应用 importScripts 进行文件的援用,可援用 url、本地 js 文件
importScripts('xxxxxxx')
// importScripts('xxxxxxx', 'xxxxxxxx') 也能够传多个
// 模仿数据处理
function handleData(num) {for (let i = 0; i < num; i++) {
let str = ''
while (str.length < 150) {str += '哈'}
}
}
onmessage = async (e) => {console.time('解决数据工夫')
const res = handleData(e.data)
postMessage('解决完了')
console.timeEnd('解决数据工夫')
}
成果
咱们再来看看代码和渲染的成果,跟方才一开始的比照下:
图片渲染也没有被阻塞:
勾销过程
能够应用 terminate
办法完结过程
worker.onmessage = (e) => {
// 报错时马上终止指定 worker 过程
worker.terminate()
console.log(e.data)
}
集体了解
其实 Web Worker
实质上并没有扭转 JavaScript 单线程
这一事实,它借助的是 浏览器的多线程
结语
我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜爱前端,想学习前端,那咱们能够交朋友,一起摸鱼哈哈,摸鱼群,加我请备注【思否】