如何在JS中检查ArrayBuffer是否已分离或转移?

问题描述 投票:0回答:3

我最近正在使用 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
来防止这个错误。但问题是:有什么方法可以知道缓冲区是否已传输?

javascript buffer web-worker arraybuffer
3个回答
4
投票

分离的 ArrayBuffer 的

byteLength
属性和使用此 ArrayBuffer 的每个类型化数组都将为零。

我不确定 SmartBuffer 库的内部结构,但此检查应该有效:

someBuffer.byteLength === 0

如果您想检查初始字节长度为零的 ArrayBuffer,这当然没有帮助。在这种情况下,如果分离,什么都不会改变。但我认为这只是理论上的问题。


2
投票

您可以使用

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


1
投票

在 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
}
© www.soinside.com 2019 - 2024. All rights reserved.