从 javascript 对象中提取 Transferable 列表?
Extract a list of Transferable from a javascript object?
Worker 接口的 postMessage() 方法允许传递一个 transferList
这是一个对象数组,其引用应该被传递(而不是被复制的对象)。
myWorker.postMessage(aMessage, transferList);
有没有一种安全的方法可以递归地提取所有可以传递其引用的对象(根据API,只有MessagePort and ArrayBuffer),所以我们不必担心传递所有其中手动?
myWorker.postMessage(aMessage, extractTransferList(aMessage));
是否建议实施此行为?
示例:
当我们考虑以下代码时:
var objData =
{
str: "string",
i8: new Int8Array(200),
obj : {
num : 8,
ab: new ArrayBuffer(100)
}
};
objWorker.postMessage(objData, [objData.i8.buffer, objData.obj.ab]);
我们需要在第二个参数中指定应该传递其引用的对象的所有字段。我的问题是关于构建一个为我们完成工作的函数,以确保我们不会忘记这里的一些可转移对象(这可能会在我们不知情的情况下影响性能)。
objWorker.postMessage(objData, extractTransferList(objData));
My question is about building a function that does the job for us, to make sure that we don't forget some transferable objects here (that could impact performances without us knowing it).
您可以实现一个函数,通过对象图递归查找可传输对象并构建它们的数组,例如:
// *Sketch*, not debugged code!!
function getTransferrables(obj, array) {
var key, value;
if (!array) {
array = [];
}
for (key in obj) {
// (Add a hasOwnProperty check here if you want one)
value = obj[key];
if (value !== null) {
if (typeof value === "object") {
if (isTransferrable(value)) {
array.push(value);
} else { // I *think* you want an else here, or should we recurse into transferrables?
getTransferrables(value, array);
}
}
}
}
return array;
}
var toString = Object.prototype.toString;
function isTransferrable(obj) {
switch (toString.call(obj)) {
case "[object MessagePort]": // I checked these on Chrome and Firefox,
case "[object Int8Array]": // you'll want to verify on your target
case "[object Int16Array]": // browsers!
// ...etc...
return true;
default:
return false;
}
}
然后你会像这样使用 getTransferrables
:
foo.postMessage(obj, getTransferrables(obj));
如果您发现 isTransferrable
中的 toString
技巧在跨浏览器方面不可靠,您可以使用对象的 constructor
属性 代替,例如:
var ctor = obj.constructor;
return ctor === MessagePort ||
ctor === Int8Array ||
ctor === Int16Array ||
// ...
;
您必须检查哪个(如果有的话)更可靠,甚至可能必须将两者混合以获得良好的跨浏览器覆盖率。
您会注意到我没有在 isTransferrable
中使用 instanceof
,这看起来很有用。问题是类型化数组在 ES2015 中是 subclassable:
class MyNiftyArray extends Int32Array {
// ...
}
当你这样做时,MyNiftyArray
的实例是 instanceof
基础 class:
let a = new MyNiftyArray();
console.log(a instanceof Int32Array); // true
...但我们不知道 subclass 实例实际上是可转移的。
但是,如果你只在你自己的代码中使用这些东西,并且你知道你永远不会子class一个可转移的类型,你确实可以使用instanceof
.
// Relies on knowing that `obj` is not an instance of a subclass of a
// tranferrable
function isTransferrable(obj) {
return obj instanceof MessagePort ||
obj instanceof Int8Array ||
obj instanceof Int16Array ||
// ...
;
}
Worker 接口的 postMessage() 方法允许传递一个 transferList
这是一个对象数组,其引用应该被传递(而不是被复制的对象)。
myWorker.postMessage(aMessage, transferList);
有没有一种安全的方法可以递归地提取所有可以传递其引用的对象(根据API,只有MessagePort and ArrayBuffer),所以我们不必担心传递所有其中手动?
myWorker.postMessage(aMessage, extractTransferList(aMessage));
是否建议实施此行为?
示例:
当我们考虑以下代码时:
var objData =
{
str: "string",
i8: new Int8Array(200),
obj : {
num : 8,
ab: new ArrayBuffer(100)
}
};
objWorker.postMessage(objData, [objData.i8.buffer, objData.obj.ab]);
我们需要在第二个参数中指定应该传递其引用的对象的所有字段。我的问题是关于构建一个为我们完成工作的函数,以确保我们不会忘记这里的一些可转移对象(这可能会在我们不知情的情况下影响性能)。
objWorker.postMessage(objData, extractTransferList(objData));
My question is about building a function that does the job for us, to make sure that we don't forget some transferable objects here (that could impact performances without us knowing it).
您可以实现一个函数,通过对象图递归查找可传输对象并构建它们的数组,例如:
// *Sketch*, not debugged code!!
function getTransferrables(obj, array) {
var key, value;
if (!array) {
array = [];
}
for (key in obj) {
// (Add a hasOwnProperty check here if you want one)
value = obj[key];
if (value !== null) {
if (typeof value === "object") {
if (isTransferrable(value)) {
array.push(value);
} else { // I *think* you want an else here, or should we recurse into transferrables?
getTransferrables(value, array);
}
}
}
}
return array;
}
var toString = Object.prototype.toString;
function isTransferrable(obj) {
switch (toString.call(obj)) {
case "[object MessagePort]": // I checked these on Chrome and Firefox,
case "[object Int8Array]": // you'll want to verify on your target
case "[object Int16Array]": // browsers!
// ...etc...
return true;
default:
return false;
}
}
然后你会像这样使用 getTransferrables
:
foo.postMessage(obj, getTransferrables(obj));
如果您发现 isTransferrable
中的 toString
技巧在跨浏览器方面不可靠,您可以使用对象的 constructor
属性 代替,例如:
var ctor = obj.constructor;
return ctor === MessagePort ||
ctor === Int8Array ||
ctor === Int16Array ||
// ...
;
您必须检查哪个(如果有的话)更可靠,甚至可能必须将两者混合以获得良好的跨浏览器覆盖率。
您会注意到我没有在 isTransferrable
中使用 instanceof
,这看起来很有用。问题是类型化数组在 ES2015 中是 subclassable:
class MyNiftyArray extends Int32Array {
// ...
}
当你这样做时,MyNiftyArray
的实例是 instanceof
基础 class:
let a = new MyNiftyArray();
console.log(a instanceof Int32Array); // true
...但我们不知道 subclass 实例实际上是可转移的。
但是,如果你只在你自己的代码中使用这些东西,并且你知道你永远不会子class一个可转移的类型,你确实可以使用instanceof
.
// Relies on knowing that `obj` is not an instance of a subclass of a
// tranferrable
function isTransferrable(obj) {
return obj instanceof MessagePort ||
obj instanceof Int8Array ||
obj instanceof Int16Array ||
// ...
;
}