Javascript 将blob内容读入现有SharedArrayBuffer
我正在试图找到将Blob的内容读入现有SharedArrayBuffer的最有效方法,这是一个工作者等待缓冲区被释放。在我的例子中,我可以保证SharedArrayBuffer的长度至少足以容纳Blob的全部内容。我想到的最好方法是:Javascript 将blob内容读入现有SharedArrayBuffer,javascript,Javascript,我正在试图找到将Blob的内容读入现有SharedArrayBuffer的最有效方法,这是一个工作者等待缓冲区被释放。在我的例子中,我可以保证SharedArrayBuffer的长度至少足以容纳Blob的全部内容。我想到的最好方法是: // Assume 'blob' is the blob we are reading // and 'buffer' is the SharedArrayBuffer. const fr = new FileReader(); fr.addEventListen
// Assume 'blob' is the blob we are reading
// and 'buffer' is the SharedArrayBuffer.
const fr = new FileReader();
fr.addEventListener('load', e =>
new Uint8Array(buffer).set(new Uint8Array(e.target.result)));
fr.readAsArrayBuffer(blob);
这似乎效率低下,尤其是当读取的blob相对较大时。
blob
不是可转移的对象。另外,文件阅读器
上没有可用的.readAsSharedArrayBuffer
方法
但是,如果您只需要同时从多个worker读取Blob
,我相信您可以通过URL.createObjectURL()
实现这一点,尽管我没有对多个worker进行测试:
// === main thread ===
let objectUrl = URL.createObjectURL(blob);
worker1.postMessage(objectUrl);
worker2.postMessage(objectUrl);
// === worker 1 & 2 ===
self.onmessage = msg => {
fetch(msg.data)
.then(res => res.blob())
.then(blob => {
doSomethingWithBlob(blob);
});
};
否则,据我所知,将数据从文件加载到SharedArrayBuffer
中确实没有有效的方法
这里我还提供了一种方法,用于将blob块从主线程传输到单个工作线程。对于我的用例,文件太大,无法将整个内容读入单个数组缓冲区(共享或不共享),因此我使用.slice
来处理块。类似这样的功能可以让您通过多个.postMessage
调用,使用Transferable
数组缓冲区,以流式方式将大量数据传送给单个工作人员:
// === main thread ===
let eof = false;
let nextBuffer = null;
let workerReady = true;
let read = 0;
function nextChunk() {
let end = read + chunkSize;
if(end >= file.length) {
end = file.length;
eof = true;
}
let slice = file.slice(read, end);
read = end;
fr.readAsArrayBuffer(slice);
}
fr.onload = event => {
let ab = event.target.result;
if(workerReady) {
worker.postMessage(ab, [ab]);
workerReady = false;
if(!eof) nextChunk();
}
else {
nextBuffer = ab;
}
};
// wait until the worker finished the last chunk
// ... otherwise we'll flood main thread's heap
worker.onmessage = msg => {
if(nextBuffer) {
worker.postMessage(nextBuffer, [nextBuffer]);
nextBuffer = null;
}
else if(!eof && msg.ready) {
nextChunk();
}
};
nextChunk();
// === worker ===
self.onmessage = msg => {
let ab = msg.data;
// ... do stuff with data ...
self.postMessage({ready:true});
};
这将把一个数据块读入主线程中的ArrayBuffer
,将其传输到辅助线程,然后在等待辅助线程处理前一个数据块的同时将下一个数据块读入内存。这基本上确保了两个线程始终处于繁忙状态。这似乎比readAsArrayBuffer方法更复杂。