We know that async
functions return a Promise implicitly. But I have a purely pedantic question. Should I put an async
keyword if I return a Promise explicitly?
Is this:
const wait = async ms => new Promise(
resolve => setTimeout(resolve, ms)
);
Any different than this?
const wait = ms => new Promise(
resolve => setTimeout(resolve, ms)
);
I believe that technically they are identical. Is there any style guide or official recommendation behind any of these two ways to define this kind of function?
CodePudding user response:
There are three main reasons I think about for using async
functions:
- You want to use
await
. - You want it to automatically catch synchronous exceptions and turn them into a rejected promise.
- You want it to always return a promise, regardless of what your function actually returns.
So, if you aren't using await
and you don't need point #2 and you are manually returning a promise already, then there's really no reason/advantage to declaring the function as async
.
A few more thoughts on the three points above.
Point #1 requires async
if you're going to use await
. There is no other way around it.
Points #2 and #3 are really just programming conveniences. If you either catch your own synchronous exceptions or are sure there are no synchronous exceptions and you are controlling all code paths to return a promise, then async
is not necessary.
Both points #2 and #3 can arise if your code has both a synchronous code path and an asynchronous code path, such as checking a cache and returning a value if its present in the cache and, if not in the cache, then make a network request to fetch the value. As described above, this can be coded manually without async
, but the code can sometimes be a little simpler with async
because it will automaticlly catch your synchronous exceptions and automatically wrap a return value in a promise.
CodePudding user response:
In the given example the async
keyword is essentially only wrapping the return value in Promise.resolve()
. See the async function documentation.
So on one hand you have:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
While on the other you have:
const wait = async ms => new Promise(resolve => setTimeout(resolve, ms));
// is similar to
const wait = ms => Promise.resolve(new Promise(resolve => setTimeout(resolve, ms)));
They are essentially the same and I would personally go for the variant without the async
keyword.
Note:
Even though the return value of an async function behaves as if it's wrapped in a
Promise.resolve
, they are not equivalent.An async function will return a different reference, whereas
Promise.resolve
returns the same reference if the given value is a promise.It can be a problem when you want to check the equality of a promise and a return value of an async function.
const p = new Promise((res, rej) => { res(1); }) async function asyncReturn() { return p; } function basicReturn() { return Promise.resolve(p); } console.log(p === basicReturn()); // true console.log(p === asyncReturn()); // false