21

有没有办法在网络工作者和主线程之间传递大量数据(多 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 中执行此操作的方法,这可能吗?

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

4

2 回答 2

15

Firefox/Opera/Chrome 目前都支持一种称为 Transferable Objects 的网络工作者,它速度极快 - 也极易设置。在这里,我们向 ww(网络工作者)发送一个浏览器分配的数组,该数组由 ww 填充并返回给浏览器端。这是通过引用传递的,而不是副本:浏览器 <-> ww

在浏览器端:

var huge_array = new Float32Array(BIG_HUSKY_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
}

通过简单地将数据对象放在方括号 [in here] 中,这会提示 js 使用 Transferable Object 模式。这也适用于来回发送包含多个变量的 javascript 对象,而不仅仅是类型化数组。

引用

可转移对象是不被复制的对象(例如使用结构化克隆之类的东西)。相反,数据从一个上下文传输到另一个上下文。调用上下文中的“版本”在转移到新上下文后不再可用。例如,当将一个 ArrayBuffer 从主应用程序传输到 Worker 时,主线程中的原始 ArrayBuffer 被清除并且不再可用。这极大地提高了向 Worker 发送数据的性能

http://html5-demos.appspot.com/static/workers/transferables/index.html https://html.spec.whatwg.org/multipage/workers.html

于 2014-12-02T05:35:02.683 回答
3

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

于 2012-10-08T23:11:43.087 回答