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

Eri*_*rik 16 javascript html5 web-worker html5-filesystem

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

  1. 使用常规postMessage方法.
  2. 使用可传输对象(仅限Chrome)
  3. 创建一个blob的URL引用,只发送URL(在Chrome中工作,在其他工作中也是如此?)

我认为(1)在发送较小的对象时很好,但是处理大于几MB的文件需要花费大量的时间和空间,因为它被序列化并作为JSON发送.Chrome提供了一种使用可转移对象传输数据的方法,其中不必复制数据.不幸的是,到目前为止,这只是Chrome的一项功能,因为它本来可以达到我的目的.

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

有没有其他方法可以用来在工作者和主线程之间传输数据?

Sco*_*and 12

Firefox/Opera/Chrome目前都支持一种叫做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
Run Code Online (Sandbox Code Playgroud)

然后在网络工作者内部:

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
}
Run Code Online (Sandbox Code Playgroud)

通过简单地将数据对象放在方括号[此处]中,这将提示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


Pir*_*nna 4

根据这个WebWorkers 教程,WebWorkers 现在支持传递 File 和 Blob 对象以及基本上任何可以与结构化克隆算法一起使用的对象......或者至少 Chrome 做到了,可能是因为它实现了 FileSystem API。我不知道这是否是主要原因,但我希望不是,事实上这个功能是在其他浏览器中实现的......能够在后台处理用户选择的文件是一件好事。