版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://cloud.tencent.com/developer/article/1347533
Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。此外,他们可以使用XMLHttpRequest执行 I/O (尽管responseXML和通道属性总是为空)。一旦创建, 一个worker 可以将消息发送到创建它的JavaScript代码, 通过将消息发布到该代码指定的事件处理程序 (反之亦然)
在worker线程中你可以运行任何你喜欢的代码,不过有一些例外情况。不能直接操作DOM
myWorker.terminate()
; work线程直接调用close()
main.js
if (window.Worker) { /
var myWorker = new Worker("worker.js");
myWorker.postMessage(['test1','test2']); //发送数据给work.js
myWorker.onmessage = function(e) { //接收来自work的数据
console.log(e.data);
};
}
work.js
onmessage = function(e) {
var mainData = e.data;
postMessage('workDate');
}
生成一个共享worker var myWorker = new SharedWorker(‘worker.js’);
myWorker.port.start(); // 父级线程中的调用
port.start(); // worker线程中的调用, 假设port变量代表一个端口
main.js
myWorker.port.postMessage('myworker');
work.js
onconnect = function(e) {
var port = e.ports[0];
port.onmessage = function(e) {
var workerResult = e.data;
port.postMessage('workjs');
}
}
在主页面与 worker 之间传递的数据是通过拷贝,而不是共享来完成的。传递给 worker 的对象需要经过序列化,接下来在另一端还需要反序列化。页面与 worker 不会共享同一个实例,最终的结果就是在每次通信结束时生成了数据的一个副本。大部分浏览器使用结构化拷贝来实现该特性。
如果你需要传输非常复杂的数据,还要同时在主页与 Worker 内调用多个方法,那么可以考虑创建一个类似下面的系统。
在主线程创建一个QueryableWorker的类,它接收worker的url、一个默认侦听函数、和一个错误处理函数作为参数,这个类将会记录所有的侦听的列表并且帮助我们与worker进行通信。代码如下:
function QueryableWorker(url, defaultListener, onError) {
var instance = this,
worker = new Worker(url),
listeners = {};
this.defaultListener = defaultListener || function() {};
if (onError) {worker.onerror = onError;}
this.postMessage = function(message) {
worker.postMessage(message);
}
this.terminate = function() {
worker.terminate();
}
this.addListeners = function(name, listener) {
listeners[name] = listener;
}
this.removeListeners = function(name) {
delete listeners[name];
}
/*
This functions takes at least one argument, the method name we want to query.
Then we can pass in the arguments that the method needs.
*/
this.sendQuery = function() {
if (arguments.length < 1) {
throw new TypeError('QueryableWorker.sendQuery takes at least one argument');
return;
}
worker.postMessage({
'queryMethod': arguments[0],
'queryArguments': Array.prototype.slice.call(arguments, 1)
});
}
worker.onmessage = function(event) {
if (event.data instanceof Object &&
event.data.hasOwnProperty('queryMethodListener') &&
event.data.hasOwnProperty('queryMethodArguments')) {
listeners[event.data.queryMethodListener].apply(instance, event.data.queryMethodArguments);
} else {
this.defaultListener.call(instance, event.data);
}
}
}
workjs代码如下
var queryableFunctions = {
getDifference: function(a, b) {
reply('printStuff', a - b);
},
waitSomeTime: function() {
setTimeout(function() {
reply('doAlert', 3, 'seconds');
}, 3000);
}
}
function reply() {
if (arguments.length < 1) {
throw new TypeError('reply - takes at least one argument');
return;
}
postMessage({
queryMethodListener: arguments[0],
queryMethodArguments: Array.prototype.slice.call(arguments, 1)
});
}
/* This method is called when main page calls QueryWorker's postMessage method directly*/
function defaultReply(message) {
// do something
}
onmessage = function(event) {
if (event.data instanceof Object &&
event.data.hasOwnProperty('queryMethod') &&
event.data.hasOwnProperty('queryMethodArguments')) {
queryableFunctions[event.data.queryMethod]
.apply(self, event.data.queryMethodArguments);
} else {
defaultReply(event.data);
}
}
除了专用和共享的web worker,还有一些其它类型的worker: