NodeJS EventEmitter: how to wait for all events to finish?

Viewed 921

Got a class, it extends EventEmitter.

Got function that fires a bunch of events on that emitter. These events trigger async tasks and they all have a done() callback.

What's the proper way to wait for all tasks to finish? I just want the process to sit there and wait for events until a certain event is fired (ALL_DONE), in which case it should exit.

I mean I know this can be done in multiple ways probably, but what I'm asking is can I do it without any packages, plugins etc, using just nodeJS APIs?

I want to wait without blocking the main thread.


EDIT:

Thx for the responses! I'm not sure these apply to my case. I should have provided more details. This is what I have:

class FoobarEmitter extends EventEmitter {
  protected checkEventStatus() {
    // this has some logic to check if all done() callbacks have been called or not. 
    if(allDone) {
     this.emit('ALL_DONE')
    }
  }
  protected fireEvents() {
    for() {
       this.emit('SOME_EVENT', () => {})
       this.checkEventStatuses();
    } 

   }

   protected registerHandlers() {
       this.on('SOME_EVENT', async (done) => {
         // does async stuff
         // might also call this.emit('OTHER_EVENT', () => {})
         done();
       })
       this.on('ALL_DONE', () => { process.exit() })
   } 
   constrcutor() {
       this.registerHandlers();
       this.fireEvents()
   }
}

new FoobarEmitter()

So this will not wait for all events. The ones fired from callbacks won't finish. Some of them runs, then the process just stopes and ALL_DONE is never fired.

1 Answers

Doesn't seem like it ought to be any more complex than something like this:

const { once, EventEmitter } = require("events");

class FooBarEmitter extends EventEmitter {
}

async function doSomethingUseful( emitter ) {
  // does something useful, emitter emits events in the process
}

async function main() {
  const emitter = new FooBarEmitter();
  const promise = doSomethingUseful(emitter) ;

  await once(emitter, "ALL_DONE");
  await promise;

}

let cc;
main()
.then( () => {
  console.log(
  cc = 0;
})
.catch( err => {
  console.error(err.stack);
  cc = 1;
})
.finally( () => {
  process.exit(cc);
});

Or, another approach:

const { once, EventEmitter } = require("events");

class FooBarEmitter extends EventEmitter {
}

async function doSomethingUseful( emitter ) {
    // does something useful, emitter emits events in the process
}

function main() {
    let promise;
    const emitter = new FooBarEmitter().on('ALL_DONE', async () => {
        await promise;
    });

    promise = doSomethingUseful(emitter) ;

}

main();
Related