Execute Program

JavaScript Concurrency: Promise Constructor Is Synchronous

Welcome to the Promise Constructor Is Synchronous lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • When we do new Promise(...) and pass a callback to the constructor, is our callback called immediately? Or is it scheduled for execution later, like then callbacks are?

  • It seems likely that it would be called asynchronously like then callbacks, at least for consistency's sake. But that's not what happens; the constructor calls the callback immediately! We can use our usual array-based instrumentation to double-check that.

  • In the next example, we'll see a result of ['before', 'constructed', 'after']. Our constructor callback is called, runs, and finishes, all before the array.push('after') line runs. Unlike then callbacks, it's not deferred at all.

  • >
    const array = [];
    array.push('before');

    new Promise(resolve => {
    array.push('constructed');
    });

    array.push('after');
    array;
    Result:
    ['before', 'constructed', 'after']Pass Icon
  • What if we add a then? Then we'll see some asynchronous behavior. Promises' then callbacks are always called asynchronously, no matter how the original promise was constructed. In our example, the output from the then shows up at the end of the array.

  • >
    const array = [];
    array.push('before');

    new Promise(resolve => {
    array.push('constructed');
    resolve();
    }).then(() => {
    array.push('then');
    });

    array.push('after');
    array;
    Asynchronous Icon Async Result:
    ['before', 'constructed', 'after', 'then']Pass Icon
  • Let's pause to work through what's happening here. First, we passed a callback function to the constructor. The promise constructor always calls its callback synchronously, so ours was called immediately and 'constructed' was pushed.

  • Second, we called then with another callback. But thens always schedule their callbacks to run asynchronously. The string 'after' was pushed, then our initial code execution finished, and only then did our then callback run.

  • The promise constructor and then both take callbacks, but it's important to remember that they call them at different times. Constructor callbacks always run immediately and synchronously, while then callbacks are scheduled to run asynchronously.

  • Finally, what if we call setTimeout in the constructor callback? Does that make it asynchronous?

  • No, the callback is always called synchronously. That's not affected by what we do inside the callback.

  • >
    const array = [];

    array.push('before');
    new Promise(resolve => {
    setTimeout(resolve, 1000);
    array.push('constructed');
    }).then(() => {
    array.push('then');
    });
    array.push('after');

    array;
    Asynchronous Icon Async Result:
    ['before', 'constructed', 'after', 'then']Pass Icon