我最近正在使用 Web Workers 和 Buffers。
现在我有一个缓冲区,我想使用 SmartBuffer 检查第六个字节。如果该字节为 0,则发送到worker1。否则,发送给worker2。
const buffer = SmartBuffer.fromBuffer(someBuffer);
if(buffer.toBuffer()[5] === 0){
worker1.postMessage(someBuffer, [someBuffer]);
}
if(buffer.toBuffer()[5] === 1){
worker2.postMessage(someBuffer, [someBuffer]);
}
由于我使用可转移对象,如果
someBuffer
已被转移,我将无法再在第5行访问它。 (这会导致错误:Cannot perform Construct on a detached ArrayBuffer
。)
我知道这是一个不好的例子,我可以简单地使用
else if
来防止这个错误。但问题是:有什么方法可以知道缓冲区是否已传输?
分离的 ArrayBuffer 的
byteLength
属性和使用此 ArrayBuffer 的每个类型化数组都将为零。
我不确定 SmartBuffer 库的内部结构,但此检查应该有效:
someBuffer.byteLength === 0
如果您想检查初始字节长度为零的 ArrayBuffer,这当然没有帮助。在这种情况下,如果分离,什么都不会改变。但我认为这只是理论上的问题。
ArrayBuffer.prototype.detached
const buffer = new ArrayBuffer(8);
console.log(buffer.detached); // false
const newBuffer = buffer.transfer();
console.log(buffer.detached); // true
console.log(newBuffer.detached); // false
旧答案
目前,检查是否已分离的最可靠方法是使用
TypedArray
构造函数。
虽然所有分离的缓冲区都会有
byteLength === 0
,但空的 ArrayBuffer
也会有,并且不被视为分离。
function isDetached(ab) {
if(ab.byteLength != 0) {
// detached buffers will always have zero byteLength
return false;
}
try {
new Uint8Array(ab);
return false;
} catch {
// Uint8Array throws if using a detached buffer
return true;
}
}
const ab = new ArrayBuffer(0);
console.log('isDetached:', isDetached(ab)); // false
structuredClone(ab, { transfer: [ab] }); // detach buffer
console.log('isDetached:', isDetached(ab)); // true
在 Node.js 中这是可能的,对于浏览器来说可能是相同的(或至少相似)。
使用
util.format()
(也用于 console.log
),将分离的 ArrayBuffer 字符串化为类似
ArrayBuffer { (detached), byteLength: 0 }
因此,检查格式化值中的
detached
会准确地告诉您这一点。
示例:
function isDetached(buffer: ArrayBuffer): boolean {
if (buffer.byteLength === 0) {
const formatted = util.format(buffer)
return formatted.includes('detached')
}
return false
}