eventemitter.emit 方法不会在节点 js 中返回

Posted

技术标签:

【中文标题】eventemitter.emit 方法不会在节点 js 中返回【英文标题】:eventemitter.emit method doesn't return in node js 【发布时间】:2019-11-24 18:07:06 【问题描述】:

我在使用 eventemitter.emit 方法时遇到问题。

基本上这就是我想要做的。我有一个生成输出对象的长时间运行的进程(受 CPU 限制),由于这是受 CPU 限制的进程,我使用 fork() 作为单独的进程运行它。

class Producer extends EventEmitter 
    constructor() 
       this.on('MyEvent', this.produce);
    

    produce(input) 
        var output = longRunningProcess();

        this.emit('MyEvent, output);
        process.send(output);
    


var producer = new Producer();
producer.emit('MyEvent', 0); // To kick off the execution

一旦生成了每个输出,我想将其发送到父进程。并且还使用它来发出事件以产生另一个对象等等。

现在,问题是process.send(output) 似乎没有被执行。我可以看到输出在控制台中一个接一个地打印出来。但是父母似乎没有从子进程中收到任何东西。据我了解,nodejs事件循环在完成当前任务并且堆栈为空之前不应该选择新任务,但这里不是这种情况。

那么你们能帮我解决这个问题吗?

编辑:父进程代码

this.producer = ChildProcess.fork('.path/to/produer.js'silent: true );
this.producer.on('message', (data) => 
    this.miningProcess.send( type: "StopMining", body: 0 );
);

【问题讨论】:

另外,请在父进程中显示接收代码的相关部分,因为这也可能是问题所在。 此外,这将无法正常工作:this.on('MyEvent', this.produce); 你需要this.on('MyEvent', this.produce.bind(this)); 这不是无限循环吗。你做producer.emit('MyEvent') 来开始。构造函数中的事件处理程序接收到它并调用this.produce(),然后再次执行this.emit('MyEvent, output);,构造函数中的事件处理程序接收到它再次启动它 - 无限循环。 @jfriend00,添加了父逻辑。现在很简单。 无限循环在 nodejs 中通常不起作用,因为您不会让事件循环处理任何可能导致网络停滞的事情。 【参考方案1】:

在我看来,您可能正在耗尽事件循环(从不给它任何循环来处理传入事件),这可能会破坏处理网络的能力,甚至是出站网络。我建议您仅在 process.send() 完成后开始下一次迭代。

class Producer extends EventEmitter 
    constructor() 
        this.on('MyEvent', this.produce.bind(this));
    

    produce(input) 
        let output = longRunningProcess();

        process.send(output, () => 
            // When the send finishes, start the next iteration
            // This should allow the node.js event queue to process things
            this.emit('MyEvent, output);
        );
    


var producer = new Producer();
producer.emit('MyEvent', 0); // To kick off the execution

其他注意事项:

    您需要在事件处理程序上使用this.produce.bind(this) 而不仅仅是this.produce,以确保在调用该函数时设置正确的this 值。 请记住,eventEmitter.emit() 是同步的。它不允许事件队列处理事件,eventEmitter 事件不会经过事件队列。 此代码假定process.send() 回调被异步调用,并为事件循环提供足够的机会来处理任何正在等待的事件。它还确保在您开始下一次 CPU 密集型迭代之前完全发送进程间消息,这将暂时阻止事件队列处理。这样,您可以确保在再次阻塞事件队列之前完成整个通信。 您可能可以使用适当的位置 setTimeout() 来启动下一次迭代,但我认为在启动下一次迭代之前确保进程间消息传递完成更可靠。 仅供参考,如果您没有使用EventEmitter 来获取除此处显示的任何内容之外的任何内容,那么它并不是真正需要的。您可以直接调用对象上的方法,而不是使用 EventEmitter 事件。

【讨论】:

添加了几个 cmets 来进一步解释一些事情。

以上是关于eventemitter.emit 方法不会在节点 js 中返回的主要内容,如果未能解决你的问题,请参考以下文章

node.js从入门到放弃

Node--01

NestJS 事件发射器

jquery中都有哪些方法可以遍历节点

dom 节点查找

父子兄弟节点查找方法