JavaScript Web Workers的构建块及5个使用场景


本文摘自PHP中文网,作者coldplay.xixi,侵删。

这是JavaScript栏目专门探索javascript及其所构建的组件的系列文章。

相关免费学习推荐:javascript(视频)

这次我们会逐步讲解 Web Workers,先说个简单的概念,接着讨论不同类型的 Web Workers,他们的组成部分是如何一起工作的,以及不同场景下它们各自优势和限制。最后,提供5个正确使用 Web Workers 的场景。

正如我们前面文章讨论的那样,你应该知道 JavaScript 语言采用的是单线程模型。然而,JavaScript 也为开发人员提供了编写异步代码的机会。

异步编程的局限性

以前的文章讨论过异步编程,以及应该在什么时候使用它。

异步编程可以让UI界面是响应式(渲染速度快)的,通过"代码调度",让需要请求时间的代码先放到在 event loop中晚一点再执行,这样就允许UI先行渲染展示。

异步编程的一个很好的用例就 AJAX 请求。由于请求可能花费大量时间,因此可以使用异步请求,在客户端等待响应的同时还可以执行其他代码。

72f4c96e35efd0d4d0f3ab1c36f7905.png

然而,这带来了一个问题――请求是由浏览器的WEB API处理的,但是如何使其他代码是异步的呢?例如,如果成功回调中的代码非常占用CPU:

1

var result = performCPUIntensiveCalculation();

如果 performCPUIntensiveCalculation 不是一个HTTP请求而是一个阻塞代码(比如一个内容很多的for loop循环),就没有办法及时清空事件循环,浏览器的 UI 渲染就会被阻塞,页面无法及时响应给用户。

这意味着异步函数只能解决一小部分 JavaScript 语言单线程中的局限性问题。

在某些情况下,可以使用 setTimeout 对长时间运行的计算阻塞的,可以使用 setTimeout暂时放入异步队列中,从让页面得到更快的渲染。例如,通过在单独的 setTimeout 调用中批处理复杂的计算,可以将它们放在事件循环中单独的“位置”上,这样可以争取为 UI 渲染/响应的执行时间。

看一个简单的函数,计算一个数字数组的平均值:

a6ee1aae4eee540542adc1b0dadcae2.png

以下是重写上述代码并“模拟”异步性的方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

function averageAsync(numbers, callback) {

    var len = numbers.length,

        sum = 0;

 

    if (len === 0) {

        return 0;

    }

 

    function calculateSumAsync(i) {

        if (i < len) {

            // Put the next function call on the event loop.

            setTimeout(function() {

                sum += numbers[i];

                calculateSumAsync(i + 1);

            }, 0);

        } else {

            // The end of the array is reached so we're invoking the callback.

            callback(sum / len);

        }

    }

 

    calculateSumAsync(0);

}

使用setTimeout函数,该函数将在事件循环中进一步添加计算的每个步骤。在每次计算之间,将有足够的时间进行其他计算,从而可以让浏览器进行渲染。

Web Worker 可以解决这个问题

HTML5为我们带来了很多新的东西,包括:

  • SSE(我们在前一篇文章中已经描述并与WebSockets进行了比较)
  • Geolocation
  • Application cache
  • Local Storage
  • Drag and Drop
  • Web Workers

Web Worker 概述

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。

你可能会问:“JavaScript不是一个单线程的语言吗?”

事实上 JavaScript 是一种不定义线程模型的语言。Web Workers 不是 JavaScript 的一部分,而是可以通过 JavaScript 访问的浏览器特性。历史上,大多数浏览器都是单线程的(当然,这已经改变了),大多数 JavaScript 实现都入发生在浏览器中。Web Workers 不是在 Node.JS 中实现的。Node.js 中有类似的集群(cluster)、子进程概念(child_process),他们也是多线程但是和 Web Workers 还是有区别 。

值得注意的是,规范 中提到了三种类型的 Web Workers:

  • 专用 Workers (Dedicated Workers)
  • 共享 Workers (Shared Workers)
  • 服务 Workers (Service workers)

Dedicated Workers

专用 Workers 只能被创建它的页面访问,并且只能与它通信。以下是浏览器支持的情况:

454e024af3f57369ef72204305fa110.png

Shared Workers

共享 Workers 在同一源(origin)下面的各种进程都可以访问它,包括:iframes、浏览器中的不同tab页(一个tab页就是一个单独的进程,所以Shared Workers可以用来实现 tab 页之间的交流)、以及其他的共享 Workers。以下是浏览器支持的情况:

f457f205b69bcd90221f574d971c316.png

Service workers

Service Worker 功能:

  • 后台消息传递
  • 网络代理,转发请求,伪造响应
  • 离线缓存
  • 消息推送

在目前阶段,Service Worker 的主要能力集中在网络代理和离线缓存上。具体的实现上,可以理解为 Service Worker 是一个能在网页关闭时仍然运行的 Web Worker。以下是浏览器支持的情况:

ca2a1948ce612cca465a5ea0cb83949.png

本文主要讨论 专用 Workers,没有特别声明的话,Web Workers、Workers都是指代的专用 Workers。

Web Workers 是如何工作

Web Workers 一般通过脚本为 .js 文件来构建,在页面中还通过了一些异步的 HTTP 请求,这些请求是完全被隐藏了的,你只需要调用 Web Worker API.

Worker 利用类线程间消息传递来实现并行性。它们保证界面的实时性、高性能和响应性呈现给用户。

Web Workers 在浏览器中的一个独立线程中运行。因此,它们执行的代码需要包含在一个单独的文件中。这一点很重要,请记住!

让我们看看基本 Workers 是如何创建的:

1

var worker = new Worker('task.js');

Worker() 构造函数的参数是一个脚本文件,该文件就是 Worker 线程所要执行的任务。由于 Worker 不能读取本地文件,所以这个脚本必须来自网络。如果下载没有成功(比如404错误),Worker 就会默默地失败。

为了启动创建的 Worker,需要调用 postMessage 方法:

1

worker.postMessage();

Web Worker 通信

为了在 Web Worker 和创建它的页面之间进行通信,需要使用 postMessage 方法或 Broadcast Channel。

postMessage 方法

新浏览器支持JSON对象作为方法的第一个参数,而旧浏览器只支持字符串。

来看一个示例,通过将 JSON 对象作为一个更“复杂”的示例传递,创建 Worker 的页面如何与之通信。传递字符串跟传递对象的方式也是一样的。

让我们来看看下面的 HTML 页面(或者更准确地说是它的一部分):

阅读剩余部分

相关阅读 >>

javascript中进程和线程的区别是什么

如何取消javascript中的异步任务?

介绍javascript作用域和闭包

深入了解js中的原始类型(primitive type)

js如何修改html

javascript中比较运算符隐式类型转换的介绍(附示例)

web开发之转发和重定向区别

javascript能做什么?

怎样使用javascript date format方法

javascript操作剪贴板的实现方法介绍

更多相关阅读请进入《javascript》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...