初始WebWorker

基本概念

JS单线程:咱们都知道JavaScript它是一个单线程的语言,同一时间只能作一件事。好比:在浏览器中,某一时刻咱们在操做DOM,大家这个时刻咱们就不能去运行JavaScript代码,反过来也是,当咱们在运行JavaScript代码的时候,咱们也不能去操做DOM,这个也就是JS的单线程。为何要JS成单线程?由于在浏览器环境下,若是是多线程的,也就是操做DOM和运行JavaScript代码是并行处理的话,假如某个时刻,浏览器正在绘制DOM,可是这个时候的JavaScript代码改变了DOM,这样就会形成一个不一致,所以JS就被设计成了一门单线程语言。node

虽然JS是单线程,可是它的宿主,咱们的浏览器环境(node环境)它是一个多线程的,在浏览器和node里面只有一条JS线程,可是还有不少其余的线程。以浏览器为例,浏览器的常驻线程(以下)大概有前三个:第一个,UI线程,也就是DOM浏览器元素的回流和重绘,这个UI线程与JavaScript线程是互斥的。第二个就是JavaScript线程,单线程的运行JS代码。第三个是GUI线程,它主要是处理与用户交互的一些逻辑,好比点击某一个元素,拖动了或者缩放了这个就是由GUI线程处理的。除此以外还有NetWorker线程,网络线程,发送ajax请求,发送http请求都是走的network线程。还有File线程,读取文件。还有一个定时器线程。web

  • UI线程 - 回流和重绘 - 与Javascript线程互斥
  • JavaScript线程 - 单线程运行JavaScript
  • GUI线程 - 交互线程
  • Network线程
  • File线程
  • 定时器线程

这里可能会有一个问题是ajax请求对于JS来讲是异步的,可是JavaScript是单线程的,这样就涉及到了一个基于事件的驱动。当咱们发起一个网络请求时,浏览器会把这一部分网络请求交给network线程去处理,而后JavaScript线程等待network的指令驱动。在没有代码要运行的状况下,JavaScript线程始终是空闲的,有了事件驱动以后,它会一直处于一个轮询的状态(Event Loop),浏览器会不断查询目前是否有JavaScript线程须要运行,若是有就运行,没有就保持闲置。当一个网络请求发送出去,这个时候的JavaScript线程是处于闲置的,可是浏览器仍是会不停的询问,当network线程结束后,浏览器发现有新的JavaScript代码须要执行,它就会驱动JavaScript的线程去处理网络请求返回的结果,这个就是JS 基于事件驱动的模型。ajax

Event Loop(事件轮询图)浏览器

异步是将耗时比较长的任务放置到Event Queue 事件队列的尾部。安全

WebWorker

WebWorker为了解决浏览器假死这个问题而孕育而生的一项新技术。它是多线程模型,也是基于宿主。它属于JavaScript线程中的一个子线程,它彻底受主线程控制,可是在WebWorker里面是不能操做DOM的。由于上面提到的UI线程和JavaScript线程是互斥的,这个互斥也就保证了DOM的惟一性,所以主的基调不能改变,可是须要有一个新的线程来分担繁杂的计算任务,这个也就是WebWorker。网络

浏览器的兼容性

应用场景

WebWorker是为了处理影响UI线程的JavaScript运算。由于在同一时刻,UI线程和JavaScript线程只能有一个在运行,若是这个时候JS的线程承担过多运算的话,它的耗时就变得很长,这个时候的UI线程是没有反应的,这样就形成了页面的假死。多线程

WebWorker特色

  • 一旦新建就会始终运行,不会被主线程打断。即便主线程卡死了,WebWorker依然在运行。
  • 同源限制,对于同一个WebWorker来说,只有同源的网页才可以访问。
  • 不能操做和访问DOM(window、document),由于要保证DOM 的惟一性。
  • 不能使用包含交互的全局方法(alert、confirm),可是可使用XMLHttpRequest、setTimeout、setInterval
  • 不能读取本地文件(不止WebWorker不能读取,JavaScript主线程也不能读取),出于安全性的考虑,浏览器是不容许js读取本地文件的。
  • WebWorker分为两个:dedicated web worker(专用线程) ,只有一个网址一个页面可使用这个线程和 shared web worker(共享线程),多个同源的网页能够共享一个WebWorker,这样为跨页面通讯提供了一种可能。

基本用法

  • 建立WebWorker异步

    const webWorker = new Worker('main.js');
    
    
    let result = 0;
    const fibonacci = (n) => {
          if (n <= 1) return 1;
          return fibonacci(n - 1) + fibonacci(n - 2);
    }
    
    result = fibonacci(10);
    console.log('result', result);
  • 向WebWorker发送消息(数据)oop

    webWorker.postMessage({ number : 10 });
  • WebWorker接收消息post

    webWorker.addEventListener('message', event => {
          console.log('received webworker data', event.data);
    }, false);
  • WebWorker发送消息(返回数据)

    this.postMessage(returnValue);
  • 主线程接收WebWorker消息

    webWorker.addEventListener('message', event => {
          console.log('received webworker data', event.data);
    }, false);
  • 关闭WebWorker

    方式一:在主线程关闭WebWorker
    webWorker.terminate();
    
    方式二:在子线程,WebWorker内部本身调用本身的close方法,再也不接收新的 Macrotask(宏任务)
    this.close();

WebWorker调用脚本

importScripts('./one.js', './two.js');

WebWorker错误监听

webWorker.addEventListener('error', error => {
    console.error(error.filename, error.lineno, error.message);
});
相关文章
相关标签/搜索