有没有办法在Web worker和主线程之间传递大量数据(多个MB)?我在一个项目中工作,我需要下载文件,稍微修改它们,然后以某种方式让用户下载修改后的文件。我找到了以下方法在Web worker和主UI之间传递数据
postMessage
方法。我认为(1)在发送较小的对象时很好,但是处理大于几MB的文件需要花费大量的时间和空间,因为它被序列化并作为JSON发送。 Chrome提供了一种使用可转移对象传输数据的方法,其中不必复制数据。不幸的是,到目前为止,这只是Chrome的一项功能,因为它本来可以达到我的目的。
我发现的最后一件事是,从工作人员使用self.webkitURL
创建一个blob的URL,然后只将URL引用传递给UI。这很好用,我可以将URL提供给用户,他们可以下载该文件。遗憾的是我没有找到一种方法可以在Firefox中实现,是否可能?
是否有其他方法可用于在工作者和主线程之间传输数据?
答案 0 :(得分:12)
Firefox / Opera / Chrome目前都支持a flavor of web workers called Transferable Objects这非常快 - 也非常容易设置。在这里,我们向ww(web worker)发送一个浏览器分配的数组,该数组由ww填充并返回给浏览器端。这是通过引用传递的,而不是副本:浏览器< - > WW
在浏览器方面:
var huge_array = new Float32Array(SIZE);
// worker.postMessage(huge_array.buffer); // old way
worker.postMessage(huge_array.buffer, [huge_array.buffer]); // new Trans Obj
然后在网络工作者内部:
self.onmessage = function(e) {
var flt_arr = new Float32Array(e.data);
// typically you might want to populate flt_arr here
// now send data structure back to browser
// self.postMessage(flt_arr.buffer); // old way
self.postMessage(flt_arr.buffer, [flt_arr.buffer]); // new Trans Obj way
}
简单地将数据对象放在方括号内[在这里] 这提示js使用Transferable Object模式。这也适用于发送包含多个变量的javascript对象,而不仅仅是类型化数组。
可转移对象是未复制的对象(例如使用结构化克隆之类的东西)。相反,数据从一个上下文传输到另一个上下文。一旦转移到新上下文,调用上下文中的“版本”将不再可用。例如,将ArrayBuffer从主应用程序传输到Worker时,主线程中的原始ArrayBuffer将被清除,不再可用。这极大地提高了向工作人员发送数据的性能
http://html5-demos.appspot.com/static/workers/transferables/index.html https://html.spec.whatwg.org/multipage/workers.html
答案 1 :(得分:2)
根据这个WebWorkers tutorial,WebWorkers现在支持传递File和Blob对象,基本上任何可以与structured clone algorith ...或者至少Chrome一起使用的对象都可以使用它,可能是因为它是implments FileSystem API。我不知道这是否是主要原因,但我希望不要,事实上这个功能是在其他浏览器中实现的...能够在后台处理用户选择的文件是一件好事。