Node.js 将带有函数定义的对象发送到工作线程

Posted

技术标签:

【中文标题】Node.js 将带有函数定义的对象发送到工作线程【英文标题】:Node.js sending an object with function definitions to worker thread 【发布时间】:2012-08-31 11:29:54 【问题描述】:

所以我正在使用 Node.js 开发一个项目,我想打开一些额外的线程来更有效地处理处理负载。但是我正在使用带有函数定义的类,当我尝试将这些对象发送到工作线程时,对象中定义的函数消失了,我只剩下对象中的其他字段。有没有办法向工作人员发送一个对象并保留函数以便在工作人员中调用它们?

var cluster = require('cluster');

if(cluster.isMaster)
    Monster = function(species)
        this.attack = function()
            console.log('CHOMP');
        ;
        this.name = species;
    ;
    var vamp = new Monster('vampire'),
    worker   = cluster.fork();
    worker.send('monster' : vamp);
    
else
    process.on('message', function(msg) 
        console.log(msg.monster); //this logs " name: 'vampire' "  
        msg.monster.attack(); //TypeError: Object #<Object> has no method 'attack'
    );

【问题讨论】:

困惑:你的问题的标题和文本很有趣,对我来说有意义,到 2021 年为止。但是代码示例是不相关/过时的,因为它显示了如何使用 nodejs 集群来代替的 nodejs 工作线程。即使我意识到在 2012 年 nodejs 不包含工作线程。 【参考方案1】:

不,没有办法在线程之间传递函数。您只能传递 JS 普通对象(仅限数据)并使用当前线程中定义的函数处理它(例如使用接收到的数据创建新对象)。

【讨论】:

哇,这真的限制了集群模块的功能。你知道是否有计划将它添加到 Node.js 中? 此功能与 node.js 架构相反。 Node.js 事件循环在单线程中工作。集群模块只是启动新进程。他们都有自己独立的记忆。多线程架构的实现需要支持共享内存的线程以及mutexessemaphores等相关机制。这不是 node.js 的方式。 赞成。查看为什么线程之间不能共享函数的详细信息:1.nodejs.org/api/…和2.developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/…【参考方案2】:

查理,我知道你在一年前问过这个问题,但我想做一些非常相似的事情,我遇到了你还没有标记答案的问题。我想我会对它进行“刺探”,并向您展示我对您的代码所做的事情。这种组织代码的不同方式对我来说是我的 node.js 工作中非常可接受的解决方法。我很确定这为您提供了一种方法来完成您想要的事情,即使您无法以您想要的方式完成它。

在集群代码之外声明你的“类”,像这样:

var cluster = require('cluster');

var Monster = function(species)
    this.attack = function()
        console.log('CHOMP!');
    ;
    this.die = function() 
        console.log("Oh, what did I eat?  I don't feel so good....\r\n");
        process.exit(0);
    ;
    this.scare = function() 
        console.log("BOO! I am a " + this.name + "!");
    ;
    this.name = species;
;

if(cluster.isMaster)
    worker = cluster.fork();
    worker.send('species' : 'Vampire');

else
    process.on('message', function(msg) 
        if(typeof msg.species !== "undefined") 
            myMonster = new Monster(msg.species);
            myMonster.scare();
            myMonster.attack();
            myMonster.die();
        
    );

试一试,看看这是不是你能接受的答案!

【讨论】:

智能解决方案/也许是唯一可行的。但是,正如问题的标题所述,在您的代码中,没有共享“具有工作线程功能的对象”。没有工作线程,您只需派生一个进程集群,每个进程创建自己的对象。不错,但“最坏情况”选项,如果您想共享大数据对象和/或包含函数(引用),则不适合。【参考方案3】:

好的,偶然发现了这个答案,我觉得奇怪的是没有人提出这个问题,但它可能是一个比问题更现代的功能:

eval

let str = "() =>  console.log('test') "
let func = eval(str)
func()

认为这里发生的事情很明显,您可以将任何字符串解析为 javascript,并且可以将字符串发送给工作人员,因此您可以使用函数构建和对象:

let obj =  a: "() =>  ... " 

然后将对象发送过来。 (首先是 JSON.stringify(obj),然后你必须先解析对象,然后再分别解析所有子字符串)

【讨论】:

这是潜在的危险,尤其是在可以访问系统其他部分的节点服务器上。想象一下,有人上传了一个名为return (function () /* arbitrary code*/ )(); 的文件,并且在您的班级中,不知何故该文件名最终被传递给eval 而不是您的函数。这不太可能,但在服务器代码中使用 eval 只会给您的系统带来更多漏洞。 如果您要评估请求,我完全同意。但是,在 OP 的情况下,他将自己的代码发送给工作人员,因此“eval”确实是 IMO 的最佳解决方案。 'eval' is honestly the best solution,除非你知道你可以serialise functions。老实说,if 所讨论的函数不是执行计算的函数,将其包装为回调,监听它自己的个性化 postMessage 实际上是最好的解决方案(任何闭包都有额外的好处和类实例继续工作;因为它们从未离开原始线程)

以上是关于Node.js 将带有函数定义的对象发送到工作线程的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有 ArrayBuffer 的 JSON 对象发送到 websocket?

在无状态 Node.js 应用程序中调度函数调用

如何将 JavaScript 对象/数组发送到前端 - node.js 应用程序

Node.js:登录后在 URL 中发送带有令牌(JWT)的新请求

使用 Node.js 将对象写入文件

使用 Node.js 将对象写入文件