据我所知,web worker需要写在一个单独的JavaScript文件中,并像这样调用:
new Worker('longrunning.js')
我正在使用闭包编译器来合并和缩小我所有的JavaScript源代码,我不希望将我的worker放在单独的文件中进行分发。有什么办法可以做到吗?
new Worker(function() {
//Long-running work here
});
既然一级函数对JavaScript如此重要,为什么标准的后台工作方式必须从web服务器加载整个其他JavaScript文件呢?
这只是上面的一个补充-我在jsFiddle中有一个很好的模板用于测试web worker。而不是Blob,它使用jsFiddles ?js api:
function workerFN() {
self.onmessage = function(e) {
switch(e.data.name) {
case "" :
break;
default:
console.error("Unknown message:", e.data.name);
}
}
}
// This is a trick to generate real worker script that is loaded from server
var url = "/echo/js/?js="+encodeURIComponent("("+workerFN.toString()+")()");
var worker = new Worker(url);
worker.addEventListener("message", function(e) {
switch(e.data.name) {
case "" :
break;
default:
console.error("Unknown message:", e.data.name);
}
})
有普通的web worker模板和共享worker模板。
使用Blob方法,对于工人工厂来说是这样的:
var BuildWorker = function(foo){
var str = foo.toString()
.match(/^\s*function\s*\(\s*\)\s*\{(([\s\S](?!\}$))*[\s\S])/)[1];
return new Worker(window.URL.createObjectURL(
new Blob([str],{type:'text/javascript'})));
}
所以你可以这样使用它…
var myWorker = BuildWorker(function(){
//first line of worker
self.onmessage(){....};
//last line of worker
});
编辑:
我只是进一步扩展了这个想法,以便更容易地进行跨线程通信:bridge -worker.js。
编辑2:
上面的链接是我创建的一个要点。后来又有人把它变成了真正的回购。
我的看法是:
function BuildWorker(fn){
var str = fn.toString().match(/^[^{]+{([\s\S]+)}\s*$/m)[1];
return new Worker(window.URL.createObjectURL(
new Blob([str],{type:'text/javascript'})));
}
function createAsyncWorker(fn){
// asyncworker=createAsyncWorker(function(){
// importScripts('my_otherscript.js');
// self.onmessage = function([arg1,arg2]) {
// self.postMessage('msg from worker');
// };
// })
// await asyncworker.postMessage('arg1','value')
// await asyncworker.postMessage('arg1','value')
// asyncworker.worker.terminate()
var worker = BuildWorker(fn);
function postMessage(...message){
let external={}, promise= new Promise((resolve,reject)=>{external.resolve=resolve;external.reject=reject;})
worker.onmessage = function(message){ external.resolve(message.data)};
worker.postMessage(message); // Start the worker.
return promise;
}
return {worker,postMessage};
}
使用的例子:
autoarima = createAsyncWorker(function(){
importScripts("https://127.0.0.1:11000/arima.js")
self.onmessage=(message)=>{
let [action,arg1,arg2]=message.data
if(action=='load')
{
ARIMAPromise.then(ARIMA1 => {
ARIMA=ARIMA1
autoarima = new ARIMA({ auto: true });
// const ts = Array(10).fill(0).map((_, i) => i + Math.random() / 5)
// const arima = new ARIMA({ p: 2, d: 1, q: 2, P: 0, D: 0, Q: 0, S: 0, verbose: false }).train(ts)
// const [pred, errors] = arima.predict(10)
postMessage('ok')
});
}
if(action=='fit')
{
autoarima.fit(arg1)
postMessage('ok')
}
if(action=='predict')
{
postMessage(autoarima.predict(arg1,arg2))
}
};
})
autoarima.terminate=function(){ this.worker.terminate(); }
autoarima.load=async function(...args){return await this.postMessage('load',...args)}
autoarima.fit=async function(...args){return await this.postMessage('fit',...args)}
autoarima.predict=async function(...args){return await this.postMessage('predict',...args)}
await autoarima.load()
await autoarima.fit(b_values)
await autoarima.predict(1)