Worker是什么
Web Worker 是HTML5标准的一部分,这一规范定义了一套 API,它允许一段JavaScript程序运行在主线程之外的另外一个线程中。JavaScript语言采用的是单线程模型(同一时间只能做一件事),也就是说,所有任务只能在一个线程上完成,一次只能做一件事。web worker 对象的出现 ,就是为了javascript创造多线程环境(同一时间能做多件事),语序主线程创建worker线程,将一些任务分配给后者运行。在主线程运行的同时,worker线程(外部的其他js文件)在后台运行,两者互不干扰。
Web Worker 规范中定义了两类工作线程,分别是专用线程Dedicated Worker和共享线程 Shared Worker,其中,Dedicated Worker只能为一个页面所使用,而Shared Worker则可以被多个页面所共享。
局限性:
Web Worker处在一个自包含的执行环境中,无法访问Window对象和Document对象,
和主线程之间的通信也只能通过异步消息传递机制实现,
这就意味着,并行的修改DOM是不可能的。
怎么用
//首先判断当前浏览器是否支持web worker
if (typeof (Worker) != "undefined") { //浏览器支持web worker
if (typeof (w) == "undefined") { //w是未定义的,还没有开始计数
w = new Worker("webworker.js"); //创建一个Worker对象,利用Worker的构造函数, 构造函数的参数是这个文件脚本文件的路径
}
//onmessage是Worker对象的properties
w.onmessage = function (event) { //事件处理函数,用来处理后端的web worker传递过来的消息
// do something
};
}
else { // 浏览器不支持web worker
// do something
}
除了用现成的js脚本文件,也能写成内嵌的,用URL.createObjectURL() 方法
var myTask = `
var i = 0;
function timedCount(){
i = i+1;
postMessage(i);
setTimeout(timedCount, 1000);
}
timedCount();
`; // 这是一个字符串
var blob = new Blob([myTask]); // Bolob对象构造,第一个参数是一个列表,第二个参数options可选
var myWorker = new Worker(window.URL.createObjectURL(blob));
Blob的怎么用:
https://developer.mozilla.org/zh-CN/docs/Web/API/Blob/Blob
注意:传入 Worker 构造函数的参数 URI 必须遵循同源策略。
Worker线程的创建的是异步的,主线程代码不会阻塞在这里等待worker线程去加载、执行指定的脚本文件,
而是会立即向下继续执行后面代码。
数据通信方式
Worker 与其主页面之间的通信是通过 onmessage 事件和 postMessage() 方法实现的。
在主页面与 Worker 之间传递的数据是通过拷贝,而不是共享来完成的。
传递给 Worker 的对象需要经过序列化,接下来在另一端还需要反序列化。
Worker有两个属性:onmessage 和 onerror,他们都是函数。
var myTask = `
onmessage = function (e) {
var data = e.data;
data.push('hello');
console.log('worker:', data); // worker: [1, 2, 3, "hello"]
postMessage(data);
};
`;
var blob = new Blob([myTask]);
var myWorker = new Worker(window.URL.createObjectURL(blob));
myWorker.onmessage = function (e) {
var data = e.data;
console.log('page:', data); // page: [1, 2, 3, "hello"]
console.log('arr:', arr); // arr: [1, 2, 3]
};
var arr = [1,2,3];
myWorker.postMessage(arr);
当worker出现错误时:
var myTask = `
onmessage = function (e) {
var data = e.data;
console.log('worker:', data);
};
// 使用未声明的变量
arr.push('error');
`;
var blob = new Blob([myTask]);
var myWorker = new Worker(window.URL.createObjectURL(blob));
myWorker.onerror = function onError(e) {
// ERROR: Line 8 in blob:http://www.cnblogs.com/490a7c32-7386-4d6e-a82b-1ca0b1bf2469: Uncaught ReferenceError: arr is not defined
console.log(['ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message].join(''));
}
杀死Worker
在主页面上调用terminate()方法,可以立即杀死 worker 线程,不会留下任何机会让它完成自己的操作或清理工作。另外,Worker也可以调用自己的 close() 方法来关闭自己。
// 主页面调用
myWorker.terminate();
// Worker 线程调用
self.close();
Worker上下文
Worker的顶层是WorkerGlobalScope,不是window。