Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create an async function that waits on an event in Javascript?

How do I block on the event?

const EventEmitter = require('events').EventEmitter;
const util = require('util');

function Task() {
    EventEmitter.call(this);
    this.setMaxListeners(Infinity);

    this.dosomething = () => {
    console.log("do something");
    };

    this.run = (iter) => {
    for(i = 0; i < iter; i++) {
            this.dosomething();
        this.emit('someevent');
    }
    }

}

util.inherits(Task, EventEmitter);

task = new Task();

function do_work() {
    console.log("work 1");
    task.once('someevent', (props) => {
    console.log('event happened');
    });
    console.log("work 2");
}

do_work();
task.run(5);

Acutal Result
work 1
work 2
do something
event happened
do something
do something
do something
do something

Expected Result
work 1
do something
event happened
work 2
do something
do something
do something
do something

like image 424
Ameet Gohil Avatar asked Dec 17 '25 18:12

Ameet Gohil


1 Answers

If I understand your question correctly, then this can be achieved via a Promise that wraps the task event handler:

async function do_work() {

  console.log("work 1");

  // use a promise to block completion of do_work() function
  // until task event callback has been invoked
  await (new Promise(resolve => {

    task.once('someevent', (props) => {

      console.log('event happened');

      // Now that task callback has been invoked, "resolve" the
      // enclosing promise to allow do_work()'s execution to complete
      resolve();

    });
  }));

  console.log("work 2");
}

The idea in the code above is to wrap the task someevent handler so that the promise resolve can be invoked once the event handler has fired (ie by calling resolve()). This allows the call to do_work() to resume, to achieve the desired execution behavior.

Also, you will need to do something like this:

// Because do_work() is async, and becase you want to ensure that
// do_work() completes before starting task.run(5), you need to enclose
// these in an async function, eg doWorkThenRunTasks()
async function doWorkThenRunTasks() {

  // Call do_work asynchronously
  await do_work()

  // task.run will happen after do_work completed
  task.run(5);
}

doWorkThenRunTasks();

The addition of the async doWorkThenRunTasks() function allows you to use await in relation to do_work() to enforce execution order of task.run(5) after completion of do_work().

Hope this helps!

like image 139
Dacre Denny Avatar answered Dec 19 '25 09:12

Dacre Denny



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!