javascript - 从 javascript 对象中提取 Transferable 列表?

标签 javascript web-worker worker

postMessage() Worker 接口(interface)的方法允许传递一个 transferList,它是一个对象数组,其引用应该被传递(而不是被复制的对象)。

myWorker.postMessage(aMessage, transferList);

有没有一种安全的方法可以递归地提取所有可以传递其引用的对象(根据 API,只有 MessagePortArrayBuffer ),这样我们就不必担心手动传递所有这些对象?

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));

如果您发现 toString把戏 isTransferrable跨浏览器不可靠,你可以使用 constructor而是对象的属性,例如:

var ctor = obj.constructor;
return ctor === MessagePort ||
       ctor === Int8Array ||
       ctor === Int16Array ||
       // ...
       ;

您必须检查哪个(如果有的话)更可靠,甚至可能必须将两者混合以获得良好的跨浏览器覆盖。

你会注意到我没有使用 instanceofisTransferrable ,这似乎很有用。问题是类型化数组在 ES2015 中是可子类化的:

class MyNiftyArray extends Int32Array {
    // ...
}

当你这样做时,MyNiftyArray 的实例是instanceof基类:

let a = new MyNiftyArray();
console.log(a instanceof Int32Array); // true

...但我们不知道子类实例实际上是可转移的。

但是,如果您只是在自己的代码中使用这些东西,并且您知道您永远不会子类化可转移类型,那么您确实可以使用 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 ||
           // ...
           ;
}

关于javascript - 从 javascript 对象中提取 Transferable 列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33168052/

相关文章:

javascript - 正则表达式 - 为什么空括号?

javascript - SocketIO : Is there a way to send a token, 每条消息?

php - 执行 SOAP 调用的工作进程生成无穷无尽的 CLOSE_WAIT 文件描述符

high-availability - HA gearman 作业服务器的最佳实践是什么

heroku - heroku 上的 worker/web dynos 的不同构建包

javascript - 为什么存在以及如何从页面 [Img inside] 中删除此空白区域

javascript - 在 HTML 中使用 Node.js 模块

javascript - 识别网络 worker 环境?

javascript - 将 Web Worker 与 Sencha Touch 2 结合使用

javascript - 使 Javascript 线程变得更快