据我所知,web worker需要写在一个单独的JavaScript文件中,并像这样调用:

new Worker('longrunning.js')

我正在使用闭包编译器来合并和缩小我所有的JavaScript源代码,我不希望将我的worker放在单独的文件中进行分发。有什么办法可以做到吗?

new Worker(function() {
    //Long-running work here
});

既然一级函数对JavaScript如此重要,为什么标准的后台工作方式必须从web服务器加载整个其他JavaScript文件呢?


当前回答

我发现CodePen目前不语法高亮内联<script>标签,不是type="text/javascript"(或没有类型属性)。

因此,我设计了一个类似但略有不同的解决方案,使用带break的标记块,这是摆脱<script>标记而不创建包装器函数(这是不必要的)的唯一方法。

<!DOCTYPE html> <script id="worker1"> worker: { // Labeled block wrapper if (typeof window === 'object') break worker; // Bail if we're not a Worker self.onmessage = function(e) { self.postMessage('msg from worker'); }; // Rest of your worker code goes here. } </script> <script> var blob = new Blob([ document.querySelector('#worker1').textContent ], { type: "text/javascript" }) // Note: window.webkitURL.createObjectURL() in Chrome 10+. var worker = new Worker(window.URL.createObjectURL(blob)); worker.onmessage = function(e) { console.log("Received: " + e.data); } worker.postMessage("hello"); // Start the worker. </script>

其他回答

一个更好的阅读方式为内联工人..

    var worker_fn = function(e) 
    {
        self.postMessage('msg from worker');            
    };

    var blob = new Blob(["onmessage ="+worker_fn.toString()], { type: "text/javascript" });

    var worker = new Worker(window.URL.createObjectURL(blob));
    worker.onmessage = function(e) 
    {
       alert(e.data);
    };
    worker.postMessage("start"); 

控制台:

var worker=new Worker(window.URL.createObjectURL(new Blob([function(){
  //Long-running work here
  postMessage('done');
}.toString().split('\n').slice(1,-1).join('\n')],{type:'text/javascript'})));

worker.addEventListener('message',function(event){
  console.log(event.data);
});

尝试使用jThread。https://github.com/cheprasov/jThread

// You can use simple calling like this
jThread(
    function(arr){
        //... some code for Worker
        return arr;
    }
    ,function(arr){
        //... done code
    }
)( [1,2,3,4,5,6,7] ); // some params

我的看法是:

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)

有一些答案,但这里是另一个内联版本。

注意:“self”参数纯粹是为了检测目的而做的修饰,实际的工作代码从第一个大括号开始,self是正常的

inlineWorker ( "hello world",// initial message to send to worker function(self){ // inline worker code. self.onmessage = function (e) { self.postMessage("thinking..."); for (var i=0;i<100000000;i++) { var r = Math.random(); } self.postMessage(e.data.toUpperCase()); } },function(e){ // optional message handler document.getElementById("log").innerHTML= "from worker:"+e.data; }); function inlineWorker (msg,fn,onMsg) { var w=window, U=!!w.webkitURL?w.webkitURL:w.URL, src=fn.toString(), s=src.indexOf('{'), e=src.lastIndexOf('}'), worker = new Worker(U.createObjectURL( new Blob([ src.substring(s+1,e-1) ], { type: "text/javascript" }) )); if (typeof onMsg==="function") { worker.addEventListener("message",onMsg); } if (msg) { worker.postMessage(msg); } return worker; } <div id="log"></div>