在Web worker和主线程之间传递大量数据

时间:2012-10-05 12:14:20

标签: javascript html5 web-worker html5-filesystem

有没有办法在Web worker和主线程之间传递大量数据(多个MB)?我在一个项目中工作,我需要下载文件,稍微修改它们,然后以某种方式让用户下载修改后的文件。我找到了以下方法在Web worker和主UI之间传递数据

  1. 使用常规postMessage方法。
  2. 使用可转让对象(仅限Chrome)
  3. 创建对blob的网址引用,只发送网址(在Chrome中也适用,在其他网站中也可以使用?)
  4. 我认为(1)在发送较小的对象时很好,但是处理大于几MB的文件需要花费大量的时间和空间,因为它被序列化并作为JSON发送。 Chrome提供了一种使用可转移对象传输数据的方法,其中不必复制数据。不幸的是,到目前为止,这只是Chrome的一项功能,因为它本来可以达到我的目的。

    我发现的最后一件事是,从工作人员使用self.webkitURL创建一个blob的URL,然后只将URL引用传递给UI。这很好用,我可以将URL提供给用户,他们可以下载该文件。遗憾的是我没有找到一种方法可以在Firefox中实现,是否可能?

    是否有其他方法可用于在工作者和主线程之间传输数据?

2 个答案:

答案 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对象,而不仅仅是类型化数组。

To quote

  

可转移对象是未复制的对象(例如使用结构化克隆之类的东西)。相反,数据从一个上下文传输到另一个上下文。一旦转移到新上下文,调用上下文中的“版本”将不再可用。例如,将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。我不知道这是否是主要原因,但我希望不要,事实上这个功能是在其他浏览器中实现的...能够在后台处理用户选择的文件是一件好事。