前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,根底是进阶的前提是我的初心,明天给大家讲一个你们既相熟又生疏的货色——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.jsconsole.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单线程 这一事实,它借助的是 浏览器的多线程

结语

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜爱前端,想学习前端,那咱们能够交朋友,一起摸鱼哈哈,摸鱼群,加我请备注【思否】