前端 Web Workers 究竟是什么?

之前咱们总说,JS是单线程没有多线程,当JS在页面中运行长耗时同步任务的时候就会致使页面假死影响用户体验,从而须要设置把任务放在任务队列中;执行任务队列中的任务也并不是多线程进行的,然而如今HTML5提供了咱们前端开发这样的能力 - Web Workers API,咱们一块儿来看一看 Web Worker 是什么,怎么去使用它,在实际生产中如何去用它来进行产出。前端

  1. 概述

Web Workers 使得一个Web应用程序能够在与主执行线程分离的后台线程中运行一个脚本操做。这样作的好处是能够在一个单独的线程中执行费时的处理任务,从而容许主(一般是UI)线程运行而不被阻塞。ajax

它的做用就是给JS创造多线程运行环境,容许主线程建立worker线程,分配任务给后者,主线程运行的同时worker线程也在运行,相互不干扰,在worker线程运行结束后把结果返回给主线程。这样作的好处是主线程能够把计算密集型或高延迟的任务交给worker线程执行,这样主线程就会变得轻松,不会被阻塞或拖慢。这并不意味着JS语言自己支持了多线程能力,而是浏览器做为宿主环境提供了JS一个多线程运行的环境。算法

不过由于worker一旦新建,就会一直运行,不会被主线程的活动打断,这样有利于随时响应主线程的通性,可是也会形成资源的浪费,因此不该过分使用,用完注意关闭。或者说:若是worker无实例引用,该worker空闲后当即会被关闭;若是worker实列引用不为0,该worker空闲也不会被关闭。canvas

看一看它的兼容性api

Browser IE Edge FireFox Chrome Safari
version 10+ 12+ 3.5+ 4+ 4+浏览器

  1. 使用

2.1 限制安全

worker线程的使用有一些注意点网络

同源限制 worker线程执行的脚本文件必须和主线程的脚本文件同源,这是固然的了,总不能容许worker线程到别人电脑上处处读文件吧
文件限制 为了安全,worker线程没法读取本地文件,它所加载的脚本必须来自网络,且须要与主线程的脚本同源
DOM操做限制 worker线程在与主线程的window不一样的另外一个全局上下文中运行,其中没法读取主线程所在网页的DOM对象,也不能获取 document、 window等对象,可是能够获取 navigator、 location(只读)、XMLHttpRequest、 setTimeout族等浏览器API。
通讯限制 worker线程与主线程不在同一个上下文,不能直接通讯,须要经过 postMessage方法来通讯。
脚本限制 worker线程不能执行 alert、 confirm,但可使用 XMLHttpRequest 对象发出ajax请求。
2.2 例子多线程

在主线程中生成 Worker 线程很容易:异步

clipboard.png

Worker()构造函数,第一个参数是脚本的网址(必须遵照同源政策),该参数是必需的,且只能加载 JS 脚本,不然报错。第二个参数是配置对象,该对象可选。它的一个做用就是指定 Worker 的名称,用来区分多个 Worker 线程。
// 主线程

clipboard.png

关于api什么的,直接上例子大概就能明白了,首先是worker线程的js文件:

clipboard.png

在HTML文件中的body中:

clipboard.png

能够本身运行一下看看效果,上面用到了一些经常使用的api

主线程中的api, worker表示是 Worker 的实例:

worker.postMessage: 主线程往worker线程发消息,消息能够是任意类型数据,包括二进制数据
worker.terminate: 主线程关闭worker线程
worker.onmessage: 指定worker线程发消息时的回调,也能够经过worker.addEventListener('message',cb)的方式
worker.onerror: 指定worker线程发生错误时的回调,也能够worker.addEventListener('error',cb)
Worker线程中全局对象为 self,表明子线程自身,这时 this指向 self,其上有一些api:

clipboard.png

  1. 实战场景

我的以为,Web Worker咱们能够当作计算器来用,须要用的时候掏出来摁一摁,不用的时候必定要收起来~

加密数据
有些加解密的算法比较复杂,或者在加解密不少数据的时候,这会很是耗费计算资源,致使UI线程无响应,所以这是使用Web Worker的好时机,使用Worker线程可让用户更加无缝的操做UI。

预取数据
有时候为了提高数据加载速度,能够提早使用Worker线程获取数据,由于Worker线程是能够是用 XMLHttpRequest 的。

预渲染
在某些渲染场景下,好比渲染复杂的canvas的时候须要计算的效果好比反射、折射、光影、材料等,这些计算的逻辑可使用Worker线程来执行,也可使用多个Worker线程,这里有个射线追踪的示例。

复杂数据处理场景
某些检索、排序、过滤、分析会很是耗费时间,这时可使用Web Worker来进行,不占用主线程。

预加载图片
有时候一个页面有不少图片,或者有几个很大的图片的时候,若是业务限制不考虑懒加载,也可使用Web Worker来加载图片,能够参考一下这篇文章的探索,这里简单提要一下。

clipboard.png

在 Web Workers 实战的时候注意:

虽然使用worker线程不会占用主线程,可是启动worker会比较耗费资源
主线程中使用XMLHttpRequest在请求过程当中浏览器另开了一个异步http请求线程,可是交互过程当中仍是要消耗主线程资源
在 Webpack 项目里面使用 Web Worker 请参照:怎么在 ES6+Webpack 下使用 Web Worker

至于还有Shared Worker、Service Worker 什么的,咱们就不看了,IE不喜欢

网上的帖子大多深浅不一,甚至有些先后矛盾,在下的文章都是学习过程当中的总结,若是发现错误,欢迎留言指出~

相关文章
相关标签/搜索