问题
web workers 需要将要执行的代码,定义为单独的js,然后通过以下方式来引用
new Worker('some/path/process.js')
但是,当工程本身需要将所有的代码进行编译并合并成一个文件时,这种单独的js的方式,就还需要一些特殊处理。
或者,当页面就是一个单独的html,不希望引用额外的js文件时,web workers本身的初始化方式都会有些不方便。
解决
根据 Worker 的 API,可以基于 Blobs 构建 Worker 实例。
目前,没有什么官方指导的方式,可以通过script标签来定义要执行的代码:
- html部分
<div id="counter"></div>
<script id="myWorker" type="text/js-worker">
// 因为type不是text/javascript, 所以不会被js引擎处理
var i = 0;
setInterval(function() {
i++;
postMessage(i);
}, 1000);
</script>
- js部分
var myWorker = null,
var workerData = new Blob([document.getElementById('myWorker').textContent], {
type: "text/javascript"
});
function init() {
// 创建worker,包含"js-worker"中定义的代码
var myWorker = new Worker(window.URL.createObjectURL(workerData));
myWorker.onmessage = function (e) {
document.getElementById('counter').innerHTML = e.data;
};
}
init();
这样,就可以把worker执行的代码,嵌套在当前的页面中,而不用单独的js文件。
更进一步方便,还可以再避免定义单独的script标签,直接将function转换为Blob的方式,如下:
function fn2workerURL(fn) {
var blob = new Blob(['('+fn.toString()+')()'], {type: 'application/javascript'})
return URL.createObjectURL(blob)
}
修改开始的例子,就可以按以下方式来写:
- 纯js部分
var myWorker = null;
var myWorker = function() {
var i = 0;
setInterval(function() {
i++;
postMessage(i);
}, 1000);
}
var workerData = new Blob(['(' + myWorker.toString() + ')()'], {
type: "text/javascript"
});
function init() {
if (typeof (Worker) === undefined) {
alert('No webworker supported');
return false;
}
myWorker = new Worker(window.URL.createObjectURL(workerData));
myWorker.onmessage = function (e) {
document.getElementById('counter').innerHTML = e.data;
};
}
init();