最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Should I define async function if I explicitly return a Promise? - Stack Overflow

programmeradmin5浏览0评论

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 remendation behind any of these two ways to define this kind of function?

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 remendation behind any of these two ways to define this kind of function?

Share Improve this question asked Oct 22, 2021 at 21:43 Robo RobokRobo Robok 22.8k20 gold badges82 silver badges141 bronze badges 2
  • 4 I wouldn't, you're not awaiting inside, so it's just syntax noise IMO – CertainPerformance Commented Oct 22, 2021 at 21:44
  • @CertainPerformance part of me agrees with your point, I feel like async keyword in JavaScript is a little confusing. I don't like it how it's required only to use with await. Is it like that in other languages too? – Robo Robok Commented Oct 22, 2021 at 21:58
Add a ment  | 

2 Answers 2

Reset to default 14

There are four main reasons I think about for using async functions:

  1. You want to use await inside that async function. In order to use await, the function containing the await MUST be marked async.
  2. You want it to automatically catch synchronous exceptions and turn them into a rejected promise.
  3. You want it to always return a promise, regardless of what your function actually returns.
  4. You like the fact that making the function async makes it clear to callers looking at the code that the function always returns a promise - essentially self documenting.

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 requirement to declaring the function as async.


A few more thoughts on the 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.

Point #4 is just a coding style preference. If you like the "self-documenting" aspects of making the function async, you can do that as an indication that it always returns a promise.


And, for anyone interested in lots of technical detail about how async functions work internlly and have been optimized over the years, this is a fairly indepth article on the topic: V8 blog on fast async.

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
发布评论

评论列表(0)

  1. 暂无评论