Synchronous and asynchronous sequential execution of functions

By Axel Rauschmayer

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

Source:: 2ality