Wait for an async function to return in Node.js

Golo Roden picture Golo Roden · Jul 24, 2013 · Viewed 13.6k times · Source

Supposed, I have a async function in Node.js, basically something such as:

var addAsync = function (first, second, callback) {
  setTimeout(function () {
    callback(null, first + second);
  }, 1 * 1000);
};

Now of course I can call this function in an asynchronous style:

addAsync(23, 42, function (err, result) {
  console.log(result); // => 65
});

What I am wondering about is whether you can make it somehow to call this function synchronously. For that, I'd like to have a wrapper function sync, which basically does the following thing:

var sync = function (fn, params) {
  var res,
      finished = false;

  fn.call(null, params[0], params[1], function (err, result) {
    res = result;
    finished = true;
  });

  while (!finished) {}

  return res;
};

Then, I'd be able to run addAsync synchronously, by calling it this way:

var sum = sync(addAsync, [23, 42]);

Note: Of course you wouldn't work using params[0] and params[1] in reality, but use the arguments array accordingly, but I wanted to keep things simple in this example.

Now, the problem is, that the above code does not work. It just blocks, as the while loop blocks and does not release the event loop.

My question is: Is it possible in any way to make this sample run as intended?

I have already experimented with setImmediate and process.nextTick and various other things, but non of them helped. Basically, what you'd need was a way to tell Node.js to please pause the current function, continue running the event loop, and getting back at a later point in time.

I know that you can achieve something similar using yield and generator functions, at least in Node.js 0.11.2 and above. But, I'm curious whether it works even without?

Please note that I am fully aware of how to do asynchronous programming in Node.js, of the event loop and all the related stuff. I am also fully aware that writing code like this is a bad idea, especially in Node.js. And I am also fully aware that an 'active wait' is a stupid idea, as well. So please don't give the advice to learn how to do it asynchronously or something like that. I know that.

The reason why I am asking is just out of curiosity and for the wish to learn.

Answer

Lucio M. Tato picture Lucio M. Tato · Aug 12, 2013

I've recently created simpler abstraction WaitFor to call async functions in sync mode (based on Fibers). It's at an early stage but works. Please try it: https://github.com/luciotato/waitfor

using WaitFor your code will be:

console.log ( wait.for ( addAsync,23,42 ) ) ;

You can call any standard nodejs async function, as if it were a sync function.

wait.for(fn,args...) fulfills the same need as the "sync" function in your example, but inside a Fiber (without blocking node's event loop)