我已经读过可以使用web worker的postmessage快速传输可转移对象.根据这个可转移的对象是arraybuffer或messageport.
问题是,如何将大尺寸(30 mb)的任意对象转换为可转移对象,并将其作为参数传递给postmessage.根据我的理解,我可以将我的数组转换为json字符串,然后将json字符串转换为原始字节数据并将其存储在数组对象中.然而,这似乎打败了快速转移的目的.
有人可以启发我将一个对象作为可转移的对象传递,或者它是否可能?
提前致谢!
这种误解在这里反复出现.您正在想象可以编写一些快速的JavaScript代码来将您的大对象转换为可转换的.但实际上,你所写的任何转换代码都会失败,就像你说的那样.数据越复杂,丢失的速度就越快.
对象通常(当不转移时)由本机结构化克隆算法转换(使用实现定义的格式并且肯定是最佳的).您编写的任何JavaScript代码很可能比结构化克隆慢,同时实现相同的目标 - 将数据转换为二进制.
可转移对象的目的是允许传输二进制数据,例如图像(来自画布),音频或视频.这些孩子的数据可以在不经过结构化克隆算法处理的情况下进行转移,为什么这是为什么可以添加可转换的接口.即使对于这些,效果也是微不足道的 - 请参阅关于可转移速度的答案.
最后一点,我写了一个基于原型的库,它将javascript对象转换为ArrayBuffer并返回.它的速度较慢,特别是JSON之类的数据.它的优点(以及您编写的任何类似代码的优点)是:
您可以定义自定义对象转换
你可以使用继承(例如发送你自己的类型,比如Foo
)
如果您的数据类似于JSON,那么只需坚持结构化克隆并且不要传输.如果您不信任我,请使用此代码进行测试.你会发现它比平常慢postMessage
.
var object = {dd:"ddd", sub:{xx:"dd"}, num:666}; var string = JSON.stringify(object); var uint8_array = new TextEncoder(document.characterSet.toLowerCase()).encode(string); var array_buffer = uint8_array.buffer; // now transfer array buffer worker.postMessage(array_buffer, [array_buffer])
相反的转换,考虑到你有一些ArrayBuffer
:
// Let me just generate some array buffer for the simulation var array_buffer = new Uint8Array([123,34,100,100,34,58,34,100,100,100,34,44,34,115,117,98,34,58,123,34,120,120,34,58,34,100,100,34,125,44,34,110,117,109,34,58,54,54,54,125]).buffer; // Now to the decoding var decoder = new TextDecoder("utf-8"); var view = new DataView(array_buffer, 0, array_buffer.byteLength); var string = decoder.decode(view); var object = JSON.parse(string);