据我所知,网络工作者需要在一个单独的JavaScript文件中编写,并像这样调用:
new Worker('longrunning.js')
我正在使用闭包编译器来组合和缩小我的所有JavaScript源代码,而我宁愿不必将我的worker放在单独的文件中进行分发 . 有办法做到这一点吗?
new Worker(function() {
//Long-running work here
});
鉴于第一类函数对JavaScript至关重要,为什么执行后台工作的标准方法必须从服务器加载整个'其他JavaScript文件?
23 回答
http://www.html5rocks.com/en/tutorials/workers/basics/#toc-inlineworkers
BLOB内联工作者的完整示例:
看看vkThread插件 . 使用htis插件,您可以在主代码中执行任何功能并在线程(Web worker)中执行它 . 因此,您无需创建特殊的“Web-worker文件” .
http://www.eslinstructor.net/vkthread/
--Vadim
https://developer.mozilla.org/es/docs/Web/Guide/Performance/Using_web_workers
Web工作者在完全独立的环境中作为单独的程序运行 .
这意味着代码不能以对象形式从一个上下文移动到另一个上下文,因为它们将能够通过属于其他上下文的闭包来引用对象 .
这一点尤其重要,因为ECMAScript被设计为单线程语言,并且由于Web工作者在不同的线程中运行,因此您将面临执行非线程安全操作的风险 .
这再次意味着需要使用源代码中的代码初始化Web worker .
来自WHATWG的规范说
但不幸的是,它并没有真正解释为什么一个人不能允许将带有源代码的字符串传递给构造函数 .
我使用这样的代码,您可以将onmessage定义为纯文本以外的函数,因此编辑器可以突出显示您的代码和jshint的工作原理 .
我发现CodePen当前没有语法高亮显示不是
type="text/javascript"
的内联<script>
标签(或没有类型属性的标签) .所以我设计了一个类似但略有不同的解决方案,使用labeled blocks和
break
,这是你可以从<script>
标签保释而不创建包装函数的唯一方法(这是不必要的) .所以我认为我们现在有另一个很酷的选择,这要归功于ES6中的模板文字 . 这允许我们省去额外的工作者函数(及其奇怪的范围),并且只是将作为工作者的代码编写为多行文本,就像我们用来存储文本的情况一样,但实际上不需要文档或DOM这样做 . 例如:
这是gist of the rest of that approach .
请注意,我们可以将所需的任何额外函数依赖项引入到worker中,只需将它们收集到一个数组中并在每个函数上运行.toString以将它们缩减为字符串(只要它们是函数声明就应该工作)和然后只是将其添加到脚本字符串中 . 这样我们就不必将我们可能已经捆绑的importScripts捆绑到我们正在编写的代码范围内 .
这个特定版本唯一真正的缺点是,linters将无法lint服务工作者代码(因为它只是一个字符串),这对于“单独的工作者函数方法”是一个优势 .
使用
Blob
方法,如何为工厂工厂:所以你可以像这样使用它......
EDIT:
我刚刚进一步扩展了这个想法,以便更容易进行跨线程通信:bridged-worker.js .
EDIT 2:
以上链接是我创建的要点 . 其他人后来把它变成了actual repo .
最近回答(2018)
你可以使用Greenlet:
例:
根据您的使用情况,您可以使用类似的东西
一个例子是
您可以将worker.js文件的内容放在反引号中(允许多行字符串常量)并从blob中创建这样的worker:
如果由于某种原因您不希望为工作者提供单独的脚本标记,这将非常方便 .
使用我的小插件https://github.com/zevero/worker-create
我认为更好的方法是使用Blob对象,下面你可以看到一个简单的例 .
您可以创建一个知道其执行上下文的JavaScript文件,并且可以充当父脚本和工作者 . 让我们从这样一个文件的基本结构开始:
如您所见,该脚本包含父's and the worker'视点的所有代码,检查其自己的单个实例是否是具有
!document
的工作程序 . 稍微笨拙的script_path
计算用于准确计算脚本相对于父页面的路径,因为提供给new Worker
的路径是相对于父页面而不是脚本 .采取Adria的回应并将其置于可复制的功能中,该功能适用于当前的Chrome和FF但不适用于IE10(来自blob的工作人员会导致security error) .
这是一个有效的例子http://jsfiddle.net/ubershmekel/YYzvr/
这只是上面的一个补充 - 我有一个很好的模板来测试jsFiddle中的web worker . 而不是Blob它使用jsFiddles
?js
api:正常web worker和shared worker模板可用 .
控制台:
一个简单的promisified版本
Function#callAsWorker
,它接受thisArg和参数(就像call
),并返回一个promise:您可以使用内联Web工作者在同一个javascript中使用Web worker .
下面的文章将向您介绍如何轻松了解Web工作者及其对Web工作者的限制和调试 .
Mastering in webworkers
内联工作者更好的阅读方式..
尝试使用jThread . https://github.com/cheprasov/jThread
Yes, it is possible, I did it using Blob files and passing a callback
我将向您展示我编写的类是什么以及它如何在后台管理回调的执行 .
首先使用
Web Worker
中正在执行的任何数据实例化GenericWebWorker
,其中包括您要使用的函数,在本例中为数字,日期和函数blocker
该阻塞函数将在n毫秒内执行无限长时间
然后你像这样使用它
将HTML工作者代码嵌入HTML的html5rocks解决方案相当糟糕 .
并且一堆逃脱的JavaScript-as-a-string并不是更好,尤其是因为它使工作流复杂化(Closure编译器无法对字符串进行操作) .
我个人非常喜欢toString方法,但@dan-man那个正则表达式!
我的首选方法:
支持是这三个表的交集:
http://caniuse.com/#feat=webworkers
http://caniuse.com/#feat=blobbuilder
http://caniuse.com/#feat=bloburls
但这不适用于 SharedWorker ,因为即使可选的'name'参数匹配,URL也必须完全匹配 . 对于SharedWorker,您需要一个单独的JavaScript文件 .
2015 update - ServiceWorker奇点到来
现在有一个更强大的方法来解决这个问题 . 再次,将worker代码存储为函数(而不是静态字符串)并使用.toString()进行转换,然后将代码插入到您选择的静态URL下的CacheStorage中 .
有两种可能的后退 . ObjectURL如上所述,或者更无缝地将 real JavaScript文件放在/my_workers/worker1.js上
这种方法的优点是:
也可以支持SharedWorkers .
选项卡可以在固定地址共享单个缓存副本 . blob方法为每个选项卡增加随机objectURL .