JavaScript线程介绍:
以前我们编写JavaScript脚本时,总是只有一条"程序执行流",也就是只有一条线程,如果JavaScript脚本执行时被阻塞了,那么就会阻塞整个JavaScript脚本的执行流程,甚至导致浏览器失去响应。在传统的JavaScript脚本编程中,开发人员无法启动子线程来执行JavaScript脚本。
Worker的出现改变了这种局面,开发者只要创建一个Worker对象,即可启动一条新的后退JavaScript线程,这意味着JavaScript并发编程时代的到来。通过JavaScript的多线程支持,我们可以把一个耗时的任务交给子线程去执行,从而避免这个耗时的任务阻塞当前执行流,避免阻塞浏览器。
Worker子线程的用法简单、方便,开发者只要传入一个JavaScript脚本的URL,创建一个Worker对象,浏览器就会启动一条线程来执行这段JavaScript脚本。如果需要与Worker线程交换数据,Worker提供了postMessage(data)方法和onmessage事件监听器属性。也就是说,使用Worker进行多线程编程非常简单。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
在前面介绍的所有JavaScript代码中,所有的JavaScript脚本都在主线程中执行。如果当前脚本包含复杂的、耗时的代码,那么JavaScript脚本的执行将会被阻塞,甚至整个浏览器都会提示失去响应。
例子:假设程序需要计算、收集从1-99999之间的所有质数(在大于1的自然数中,除了1和该整数自身外,没法被其他自然数整除的数),如果程序不采用后台线程,而是直接使用JavaScript前台线程计算、收集质数。
代码解释:当前台JavaScript脚本需要执行一个耗时的任务时,JavaScript脚本会阻塞前台浏览器。只有当整个JavaScript脚本执行完成后,浏览器才会显示出这段JavaScript脚本的执行结果。如果需要继续增大收集的范围,比如要收集1-999999之间的质数,那就可能导致浏览器停止响应了。
如果改为使用Web Worker启动多线程来执行这个任务,那么页面效果就完全不同了。使用Worker创建多线程非常简单,只要调用Worker的构造器即可。Worker提供了如下构造器。
▶Worker(scriptURL):scriptURL用于指定所使用JavaScript脚本的路径。
代码解释:上面程序中的粗体字代码以worker.js为参数,创建另一个worker对象,这就相当于创建了一条线程--换句话来说,worker.js脚本将会被放在另一个"程序执行流"中执行,worker.js的执行就不会阻塞前台线程,更不会阻塞浏览器。下面是worker.js脚本的代码:
代码解释:Worker启动的子线程找到质数之后,并不能直接把找到的质数更新在页面上显示,而是必须通过postMessage(n);发送消息来与前台JavaScript通信。使用Worker创建的多线程执行时有一个限制,Worker启动的多线程不允许使用DOMAPI,包括Node对象及其子元素对象、Document对象等。换句话来说,Worker启动的多线程不能直接更新前台HTML页面。