JavaScript 周报 436 期之 WebWorker 是什么

本周 JavaScript 436期周报连接。这里面主要我想谈谈 WebWorker 相关的内容。javascript

众所周知,JavaScript 使用运行在单线程上的。可是 JavaScript 能够处理异步代码,其中 Ajax 就是个很好的例子。异步带来的用户体验没必要多说,可是这里有个问题:若是异步以后的成功回调是一次密集 CPU 操做。那么原本由于异步而产生的非阻塞用户体验,就又会由于没法从事件循环出解脱而又产生阻塞。对用户而言便又产生了不响应的 UI。这种状况,咱们能够认为 JavaScript 只是解决了单线程的部分限制。能够假设,若是咱们把这一次密集 CPU 操做也在异步中执行,那么用户体验仍然一如既往地流畅。html

Web Worker 就应用而生了。前端

Web Workers 概述

Web Worker 是真正的多线程。java

Web Worker并不会阻塞事件循环。参考这个 demo 能够看到在 5 万条数据排序的时候,使用 WebWorker 带来的体验差异。Web Worker 并非 JavaScript 的一部分,它是经过 JavaScript 能够访问的浏览器特性。然而,Web Worker 并无在 Node.js 中实现,有点像子进程的概念,可是却有不一样。git

Web Worker是有三种类型,在 MDN 中有详细定义:github

  • 专用 Workers
  • 共享 Workers
  • 服务 Workers

其中,专用 Workers 是经过主进程实例化,也只能经过主进程通讯;共享 Workers 能够访问全部同源的进程(在不一样的浏览器标签,窗口或者其余的共享 Workers);服务 Workers 是针对源和路径的事件驱动 worker,用在网络不可用的状况下,能够控制网站和相关站点,插入和修改导航和资源请求,缓存资源等。web

如何工做

Web Workers 在浏览器中运行一个独立的线程。正因如此,执行的代码须要被包含在一个独立的文件中,这一点比较重要。使用方式也很简单:浏览器

var worker = new Worker('taks.js');
复制代码

浏览器会建立一个异步下载的文件线程。当下载完成后,会被执行。经过调用 postMessage 方法来使用建立好的 worker。它可让一个 Web Worker 和页面之间通讯。缓存

如何使用 postMessage 方法

比较新的浏览器支持 JSON 做为第一个参数,而旧的浏览器只支持字符串。安全

<button onclick="startComputation()">Start computation</button>

<script> function startComputation() { worker.postMessage({'cmd': 'average', 'data': [1, 2, 3, 4]}); } var worker = new Worker('doWork.js'); worker.addEventListener('message', function(e) { console.log(e.data); }, false); </script>
复制代码

在 new 一个 Worker 以后,给它的实例注册一个叫 message 的监听事件。同时在咱们的 doWork.js 里,也要注册相同事件用来处理数据。

self.addEventListener('message', function(e) {
  var data = e.data;
  switch (data.cmd) {
    case 'average':
      var result = calculateAverage(data); // Some function that calculates the average from the numeric array.
      self.postMessage(result);
      break;
    default:
      self.postMessage('Unknown command');
  }
}, false);
复制代码

当消息到达的时候,worker 就开始执行计算,具体来讲运行 calulateAverage 方法。结束以后,把结果传递给主页面。在 worker 的上下文环境中,selfthis 都是 worker 的全局,与 window 无关。有两种方式能够结束 worker: worker.terminate()self.close()

Web Worker 可用特性

  • navigator 对象
  • location 对象(只读)
  • XMLHttpRequest
  • setTimeout()/clearTimeout()setInterval()/clearInterval()
  • 应用缓存
  • 使用 importScripts() 导入外部脚本
  • 建立其余的 web workers

Web Worker 限制

  • DOM(很显然,多线程的操做DOM是不合理和不安全的)
  • window 对象
  • document 对象
  • parent 对象

几个 Web Workers 的场景

  • 光线追踪

    为了模拟光线路径,这种场景是须要大量计算的,可是不能再每次大量计算的时候就让光线变得卡顿或者不天然,这时候workers 就能够发挥做用了。

  • 加密

    也是纯粹的计算工做,交给 web workers 正当其用。并且有些加密解密的操做是至关消耗时间的。

  • 预加载数据 当网络不是很稳定的时候,能够先把数据取出来存在本地浏览器缓存中,这样在须要的时候就会减小延迟感

  • 拼写检查

    若是对应的检查数据是一本字典的话。这种场景下,使用 web worker 就十分必要了。

总结一下使用 Web Workers 的场景的共同点:

  1. 延迟甚至不须要 DOM 操做的状况
  2. 短期使用产生大量计算,会阻塞 UI 线程,致使卡顿的场景
  3. 预处理,异步处理的部分场景

小结

Web Worker 是个浏览器实现的特性,尽管如此,咱们仍是可以在某些地方发挥它的优点去加强用户体验,遵循“渐进加强,平稳退化”得原则。没有理由去拒绝使用它。但其实,Web Worker 的使用场景也十分具备特色,它应该不是做为解决卡顿问题的首选,由于在前端,除了动画之外每每没有特别大的计算量。大多数的不流畅用户体验,多半是重绘和重排没有优化好而引发的,千万不可缘木求鱼,为了 Web Worker 什么都往上鼓捣。

参考资料

  1. blog.sessionstack.com/how-javascr…

pic
相关文章
相关标签/搜索