JavaScript的多线程(工作线程)简介

来源:互联网 发布:sql 变量 编辑:程序博客网 时间:2024/06/13 21:46

首先声明,标题写成多线程主要目的是吸引眼球赚点击量,程序员一般看见多线程就会肾上腺素激升,你懂的。。。

其实更精确的定义是工作线程worker thread,本篇会详细为何起名叫工作线程worker thread,而非其他语言中的多线程multi thread,两者有些许差别。


JavaScript原本是单线程的,一次只能处理一件事。如果处理数组占据大量时间,用户点击可能就没反应了,或页面刷新很慢,影响用户体验。

HTML5之后可以新建一个工作线程来处理数组,确保之后的事情能顺利完成。

工作线程大致定义如下:


由一个单独的JavaScript文件定义。要让工作线程工作,浏览器会发送一个消息,工作线程收到消息开始工作。完成工作后发回消息给浏览器。

1.HTML中加载的js相当于主线程:

<script src="js/myThread.js"></script>    //可以将HTML中加载的myThread.js理解为主线程
2.定义个worker.js,内容可以暂时为空。(为定义工作线程做准备)

3.主线程中定义工作线程,发送消息让工作线程开始工作,定义onmessage和onerror回调函数,分别处理工作线程成功或失败完成工作的事件

window.onload = function() {                        //HTML页面加载时运行代码var worker = new Worker("js/worker.js");    //将第2步新建的空的worker.js定义成工作线程(※1)worker.postMessage("startwork");            //主线程向工作线程发送消息(※2)worker.onmessage = function(event) {        //工作线程成功完成工作后的回调函数(※3)            document.getElementById("output").innerHTML = event.data;  }worker.onerror = function(error) {          //工作线程完成工作失败后的回调函数(※3)document.getElementById("output").innerHTML ="There was an error in " + error.filename + " at line number " + error.lineno +": " + error.message;};}
※1:只能用一个js文件创建工作线程,而不能用函数。因为规定工作线程不能访问DOM,如果向Worker构造函数传入一个函数,该函数可能包含DOM或主JavaScript代码的引用,就违反规则。因此工作线程的设计者选择的做法是只能传递一个js文件的URL

※2:消息可以是一个简单的字符串,也可以更复杂如worker.postMessage([1,2,3,4]);数组,worker.postMessage({“message”:“ping”, “count”: 5});JSON对象。但不能worker.postMessage(func);发送函数,理由※1

※3:回调函数的参数Event对象:我们只对data和target属性感兴趣,data属性包含工作线程发送的消息,target属性是发出这个消息的工作线程的引用,方便我们知道来自哪个工作线程


4.实现worker.js

onmessage = function(event) {if (event.data == "startwork") {    //根据主线程发来的消息,做相应的处理......                      //此处省略50行业务相关的处理工作postMessage("done!");       //工作完成,回发消息通知主线程,主线程的onmessage方法将被触发} else {postMessage("Are you sleepwalking now?");}}

工作线程注意点:

1.上面的※1已经说明过了,这里再啰嗦一遍:

工作线程无法访问浏览器代码能够访问的很多运行时的对象,如DOM或主代码中的所有变量和函数。但可以访问localStorage或做出XMLHttpRequest请求。

之所以如此设计,是因为必须保证只有一个线程能访问DOM,否则多个线程并发修改DOM会很容易导致DOM处于一种不一致的状态。

想象一下线程A为某个DOM元素增加子DOM元素,线程B删除该DOM元素。而线程之间无法保证运行顺序,如果线程B先完成,线程A取DOM元素时将会出错。

现在明白工作线程和传统意义上的多线程的区别了吧,工作线程相当于一个二等公民。


2.主线程向工作线程发送的消息对象,不会成两者间的共享对象。工作线程会得到对象的副本,工作线程中对副本的修改不会影响到主线程中该对象,工作线程发出的对象也是如此,主线程只能得到该对象的副本


何时使用工作线程:

学习了工作线程的基本原理和技术后,请不要滥用它。因为工作线程的负荷是很重的,通常数据量不大时压根没必要使用工作线程。

但在页面做图像处理时就非常有用了,不用工作线程的话,加载显示Mandelbrot分形图页面的速度将难以忍受:



0 0