简体   繁体   中英

eventemitter.emit method doesn't return in node js

I have a problem using eventemitter.emit method.

Basically this is what I want to do. I have a long running process (CPU bounded) that generates output objects, and since this is CPU bounded process i run it as a separate process using 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

And once each output is generated, I want to send it to the parent process. And also use it to emit an event to produce another object and so on.

Now, the problem is that the process.send(output) doesn't seem to be executed. I can see the outputs being printed in the console one after one. But the parent doesn't seem to be receiving anything from the child process. In my understanding, nodejs event loop shouldn't pick up a new task until it finishes the current one and the stack is empty, but this is not the case here.

So can you guys help me with this?

Edit : Parent process code

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

It looks to me like you may be starving the event loop (never giving it any cycles to processing incoming events) which can wreck the ability to process networking, even outbound networking. I'd suggest that you start the next iteration only after the process.send() has completed.

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

Other comments of note:

  1. You need this.produce.bind(this) on your event handler instead of just this.produce to make sure the right this value is set when that function is called.
  2. Keep in mind that eventEmitter.emit() is synchronous. It does not allow the event queue to process events and eventEmitter events do not go through the event queue.
  3. This code assumes that the process.send() callback is called asynchronously and gives the event loop enough chances to process any events that are waiting. It also makes sure the interprocess message is completely sent before you start the next CPU intensive iteration which will temporarily block the event queue processing again. This way, you are sure the whole communication is done before blocking the event queue again.
  4. You probably could have made things work with an appropriately places setTimeout() to kick off the next iteration, but I think it's more reliable to make sure the interprocess messaging is done before kicking off the next iteration.
  5. FYI, if you're not using the EventEmitter you derive from for anything other than is shown here, then it isn't really needed. You could just call methods on your object directly rather than using EventEmitter events.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM