- 来源页面: http://active.tutsplus.com/tutorials/html5/quick-tip-javascript-web-workers-move-hard-work-to-the-background/
- 资讯原标题: Quick Tip: JavaScript Web Workers Move Hard Work to the Background
- 资讯原作者: Maciej Sopylo
-
一个web worker(一般驿为:工作线程)就是一个在后台运行的JS脚本,与其它脚本不同的是,它允许我们在web应用程序中引入线程。虽然它不是HTML5脚本的一部分,但是web workers可以用于HTML5的应用程序。在这篇快速指南里,我们将了解如何使用它们。
Web Workers介绍
在HTML5领域,有很多有趣的APIs。它们中的一些—–比如WebWorkers—-对提高性能非常有用,这对应用程序和游戏来说很关键。但是web workers是如何工作的呢?
每一个web worker的实例都会创建另外一个线程,在那里运行JavaScript。你的实例创建可能是这样的:
var worker = new Worker(‘filename.js’);
这里,‘filename.js’是包含有你的脚本的文件名。因为Workers是独立的运行环境,所以你不能将代码直接嵌入到HTML里,你必须使用一个独立的文件。
通信: 发送和 接收数据
Workers不能访问页面的DOM或者全局对象,那么他们如何与网站通信呢?很简单,当你想让页面发送些数据到一个Worker,你只需调用postMessage()。
它只有一个参数:要发送的数据,这些数据可以是一个字符串也可以是一个可解析的JSON对象(这就意味着你不能传入一个函数或者是循环引用,否则你就会得到一个DOM_EXCEPTION错误)。在一些浏览器上,对象的解析可能会有问题,所以最好能手动解析JSON.parse()所对应的对象,这样你就不会担心会有不完整的实现了。
同理,当你从一个Worker向页面发送数据时:只需要自己调用postMessage(),它将指向这个Worker的全局域。(当然,你需要在这个Worker的脚本里做这些)
然后,为了接收数据,你必须添加一个onmessage事件处理器。就像针对普通的DOM元素的事件处理方法一样,这里有两种方法:一种是直接赋一些函数给这个Worker的onmessage属性,另一种方法是使用addEventListener()。
// First way:
worker.onmessage = function (e) {
console.log(e.data); // Log the data passed
}// Second way:
worker.addEventListener(‘message’, function (e) {
console.log(e.data); // Log the data passed
});
选择哪种方法是你的决定,但是无论选择哪种方法,函数的参数将是一个事件对象,你用postMessage()发送的数据将通过这个事件的数据属性所传递。
外部脚本和库
然后,当我们需要使用一些外部的库时该怎么办?因为我们不能访问DOM或者全局域,所以我们不能加入这个脚本。
不用担心,这里正好有一个函数可以解决这个问题。它叫做importScripts(),它有一个或者多个参数:要导入这个Worker域内的一个或者多个脚本名。需要注意的是,这个函数中,各脚本的导入顺序是随机的,但是它们的执行是指定的,而且在它们被完全导入前,脚本的执行将会暂停。
importScripts(‘one-lib.js’); // Loads one script
importScripts(‘first-lib.js’, ‘second-lib.js’, ‘third-lib.js’); // Loads three scripts
你可以在代码的任何地方使用importScripts,并在Worker内部创建JSONP请求。下面我们将举例说明。
例子:Workers
好了,我想你现在想看一个实际中的Worker实例。为了不显示一些无用的信息,比如获得一些质数或者Fibonacci数,我决定举一个你日后能在项目中能用到的例子。
样例脚本(我只包含了Worker代码,剩下的很容易做的)会从@envatoactive上获得最近的100条Tweets(我们需要设置计数为121而不是100,因为TweeterAPI发送的Tweets总是比要求的要少,不要问我为什么,我也不知道)。
这是实际运行中的Web Worker脚本代码:
// Helper function for processing the data
var process = function (data) {
// Iterate through the data; we know it’s an array, so it’s safe
for (var i = 0, v; v = data; i++) {
// And pass Tweet’s text to the page
self.postMessage({ text: v.text });
}
// After work is done, let the page know
self.postMessage(“finished”);
}// Attach event listener to handle messages
self.addEventListener(‘message’, function (event) {
// Check if command sent was ‘start’
// Not necessary here, but may be useful later
if (event.data == “start”) {
// Reply to the page that we started the work
self.postMessage(“started”);
// Core of the script, get the Tweets
// The callback parameter specifies the function to execute after the request is done
// (We call the process() function, defined above.)
// Count needs to be 121 because Tweeter API is sending lower amount of data than requested
importScripts(“http://twitter.com/statuses/user_timeline/envatoactive.json?callback=process&count=121″);
}
});从注释中很容易就可以理解了。它使用了一个独立的线程,使得你的应用程序能在后台加载所有的tweets。
现在,试着不使用web workers,在一个空白页面的头部加入同样的代码,然后关注下延迟。(它仍然很小,但是想象一下它获得的不是100条而是1000条tweets的情况)
总结
正如你所见,web workers提供了一个简单的方法来解决GUI的延迟,它将复杂的计算和网络工作分配到另外的线程中。
我希望你能从这篇文章中学到—-些新的东西—或许你在下面的一个项目中会使用Workers? ……^_^