Await equivalent of 'Promise.resolve().then()'?
Matthew Martinez
I'm familiar with Promises, but have inherited some rather unusual code that, rather than making a new Promise(), uses the following:
Promise.resolve().then( function() { // Do useful things }
)From my research, this is a weird version of setImmediate - ie, run the following function on the next tick.
What would be the await version of this?
3 Answers
There may be two different reasons for the Promise.resolve(). You touched on one of them:
Defer until the end of the current run of the JS event loop
Here the obvious answer is await Promise.resolve();.
await undefined does the same thing implicitly, but why not be explicit?
Singular error handling
Promise.resolve() is also often seen at the head of a promise chain for singular error handling:
const doSomething = x => new Promise(r => setTimeout(() => r(x), 1000));
Promise.resolve()
.then(() => doSomething(""())) // bug!
.then(() => doSomething("else"))
.catch(e => console.log("Got " + e)); // Got TypeError: "" is not a functionWithout it, the first step may throw an exception instead, which may be unexpected!
const doSomething = x => new Promise(r => setTimeout(() => r(x), 1000));
doSomething(""()) // bug!
.then(() => doSomething("else"))
.catch(e => console.log("Got " + e)); // uncaught!Here the answer is: you no longer need the Promise.resolve() prologue with async/await.
async functions implicitly catch synchronous exceptions and return a rejected promise instead, guaranteeing singular error handling and a promise return value:
const doSomething = x => new Promise(r => setTimeout(() => r(x), 1000));
(async () => { await doSomething(""()); // bug! await doSomething("else");
})().catch(e => console.log("Got " + e)); // Got TypeError: "" is not a functionNot only is this a nice invariant and less to type, unlike the Promise.resolve() kludge, it actually still calls doSomething synchronously:
function doSomething() { console.log("doSomething() called"); ""() // bug! return new Promise(r => setTimeout(() => r(x), 1000));
}
(async () => { await doSomething(); await doSomething("else");
})().catch(e => console.log("Got " + e)); // Got TypeError: "" is not a function
console.log("here");This would be pretty hard to pull off any other way. Another reason async/await is great!
4Just await something.
If you give await an expression which is not a promise, it will behave like
await Promise.resolve(<nonPromiseExpression>)So await undefined will cause the rest of the async function to be executed asynchronously. Take these two implementations of setImmediate as an example:
var setImmediate = function (fn) { Promise.resolve().then(fn);
};
console.log('A');
setImmediate(function () { console.log('E');
});
console.log('B');
setImmediate = async function (fn) { await undefined; fn();
};
console.log('C');
setImmediate(function () { console.log('F');
});
console.log('D'); 1 I have inherited some rather unusual code that, rather than making a
new Promise()uses aPromise.resolve().then(…). From my research, this is a weird version of setImmediate - ie, run the following function on the next tick.
That's a side-effect, but probably not the intended purpose of this construct. The main point is that the "useful code" in the then callback is throw-safe and can easily return plain values and promises alike, starting a usual promise chain. It could have been written with new Promise as well, but that would have required to use a resolve call instead of the usual return.
What would be the
awaitversion of this?
Literally, await Promise.resolve(); (which could be shortened to the equivalent await undefined; statement). However, if it was done for the purposes of error handling alone (which is likely), just omit it. async functions will transform exceptions into rejections by default.