Saturday, November 07, 2015

Synchronous and asynchronous sequential execution of functions

Synchronous and asynchronous sequential execution of functions

This blog post examines three ways of executing function sequentially:

  • Synchronously
  • Asynchronously, via Promises
  • Asynchronously, via the library co


Synchronously

Synchronous sequential execution is built into JavaScript and looks like this:

function func() {
 foo();
 bar();
 baz();
}

Asynchronously, via Promises

To execute Promise-based functions sequentially, you need to chain function calls via then(), which is the Promise equivalent of the semicolon:

/**
 * Returns a Promise that resolves to `undefined`.
 */
function func() {
 return foo()
 .then(() => bar())
 .then(() => baz());
}

If you are OK with executing the functions in an arbitrary order (the single-threaded version of “in parallel”), you can use Promise.all():

/**
 * Returns a Promise that resolves to
 * [undefined, undefined, undefined].
 */
function func() {
 return Promise.all([foo(), bar(), baz()]);
}

Asynchronously, via the library co

The library co also works with Promise based functions. Its main function, co(), takes a generator as a callback and suspends and resumes it as the results arrive. co() returns a Promise-based function that returns a promisified version of whatever the callback returns.

/**
 * The callback implicitly returns `undefined`.
 * Therefore, `func` returns a Promise that resolves to
 * `undefined`.
 */
const func = co(function* () {
 yield foo();
 yield bar();
 yield baz();
});

co works very much like async functions, a proposed ECMAScript feature (to appear in ES2016 or later), without being much more verbose. I prefer it to transpiling async functions via Babel, because their syntax may still change.

Further reading