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, likethencallbacks are?It seems likely that it would be called asynchronously like
thencallbacks, 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 thearray.push('after')line runs. Unlikethencallbacks, 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']
What if we add a
then? Then we'll see some asynchronous behavior. Promises'thencallbacks are always called asynchronously, no matter how the original promise was constructed. In our example, the output from thethenshows 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;Async Result:
['before', 'constructed', 'after', 'then']
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
thenwith another callback. Butthens always schedule their callbacks to run asynchronously. The string'after'was pushed, then our initial code execution finished, and only then did ourthencallback run.The promise constructor and
thenboth take callbacks, but it's important to remember that they call them at different times. Constructor callbacks always run immediately and synchronously, whilethencallbacks are scheduled to run asynchronously.Finally, what if we call
setTimeoutin 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;Async Result:
['before', 'constructed', 'after', 'then']