没有单独的 Javascript 文件的 Web 工作者?

2022-08-29 23:46:50

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

new Worker('longrunning.js')

我正在使用闭包编译器来组合和缩小我所有的JavaScript源代码,我宁愿不必让我的工人在单独的文件中进行分发。有没有办法做到这一点?

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

鉴于一流的函数对JavaScript如此重要,为什么进行后台工作的标准方法必须从Web服务器加载整个其他JavaScript文件?


答案 1

http://www.html5rocks.com/en/tutorials/workers/basics/#toc-inlineworkers

如果要动态创建工作线程脚本,或者创建独立的页面而无需创建单独的工作线程文件,该怎么办?使用 Blob(),您可以通过创建工作线程代码的 URL 句柄作为字符串,将工作线程“内联”在与主逻辑相同的 HTML 文件中


BLOB 内联工作线程的完整示例:

<!DOCTYPE html>
<script id="worker1" type="javascript/worker">
  // This script won't be parsed by JS engines because its type is javascript/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>

答案 2

在HTML中嵌入Web工作代码的html5rocks解决方案相当可怕。
一团转义的JavaScript-as-a-string也好不到哪里去,尤其是因为它使工作流程复杂化(闭包编译器不能对字符串进行操作)。

就个人而言,我真的很喜欢toString方法,但@dan人那个正则表达式!

我的首选方法:

// Build a worker from an anonymous function body
var blobURL = URL.createObjectURL( new Blob([ '(',

function(){
    //Long-running work here
}.toString(),

')()' ], { type: 'application/javascript' } ) ),

worker = new Worker( blobURL );

// Won't be needing this anymore
URL.revokeObjectURL( blobURL );

支持是这三个表的交集:

但是,这不适用于 SharedWorker,因为 URL 必须完全匹配,即使可选的“name”参数匹配也是如此。对于 SharedWorker,你需要一个单独的 JavaScript 文件。


2015年更新 - 服务工人奇点到来

现在有一种更强大的方法可以解决这个问题。同样,将工作代码存储为函数(而不是静态字符串),并使用 .toString() 进行转换,然后将代码插入到 CacheStorage 中您选择的静态 URL 下。

// Post code from window to ServiceWorker...
navigator.serviceWorker.controller.postMessage(
 [ '/my_workers/worker1.js', '(' + workerFunction1.toString() + ')()' ]
);

// Insert via ServiceWorker.onmessage. Or directly once window.caches is exposed
caches.open( 'myCache' ).then( function( cache )
{
 cache.put( '/my_workers/worker1.js',
  new Response( workerScript, { headers: {'content-type':'application/javascript'}})
 );
});

有两种可能的后备方案。如上所述的 ObjectURL,或者更无缝地将一个真正的 JavaScript 文件放在 /my_workers/worker1.js

这种方法的优点是:

  1. 还可以支持共享工作程序。
  2. 选项卡可以在固定地址共享单个缓存副本。Blob 方法会为每个选项卡增殖随机对象 URL。