我们知道async
函数隐式返回一个Promise。但我有一个纯粹迂腐的问题。我应该把async
关键字,如果我返回一个承诺显式?
:
const wait = async ms => new Promise(
resolve => setTimeout(resolve, ms)
);
和这个有什么不同吗?
const wait = ms => new Promise(
resolve => setTimeout(resolve, ms)
);
我相信在技术上它们是相同的。在这两种定义这类函数的方法背后有什么风格指南或官方推荐吗?
我认为使用async
函数有四个主要原因:
- 您要使用
await
- 你想让它自动捕捉同步异常,并把它们变成一个被拒绝的承诺。
- 你希望它总是返回一个承诺,不管你的函数实际返回什么。
- 你喜欢这样一个事实,即使函数
async
使查看代码的调用者清楚地知道函数总是返回一个承诺-本质上是自我记录。
所以,如果你不使用await
,你不需要第2点,你已经手动返回一个承诺,那么真的没有必要将函数声明为async
。
关于以上几点的几点思考。
如果你打算使用await
,第1点需要async
。没有别的办法了。
第2点和第3点实际上只是编程方便。如果你捕获自己的同步异常,或者确定没有同步异常,并且控制所有代码路径返回承诺,那么async
是不必要的。
async
的情况下手工编写,但使用async
有时代码会简单一些,因为它会自动捕获同步异常并自动将返回值包装在承诺中。
第4点只是一种编码风格偏好。如果你喜欢"自我记录"在创建async
函数的几个方面,你可以这样做,作为一个指示,它总是返回一个承诺。
并且,对于那些对async
函数如何在内部工作以及多年来如何优化的技术细节感兴趣的人来说,这是一篇关于该主题的相当深入的文章:V8博客关于快速异步。
在给定的示例中,async
关键字实际上只是将返回值包装在Promise.resolve()
中。参见async函数文档。
所以一方面你有:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
另一边是:
const wait = async ms => new Promise(resolve => setTimeout(resolve, ms));
// is similar to
const wait = ms => Promise.resolve(new Promise(resolve => setTimeout(resolve, ms)));
它们本质上是相同的,我个人会选择没有async
关键字的变体。
注意:
尽管async函数的返回值的行为就好像它是在
Promise.resolve
中,它们不相等。async函数将返回不同的引用,而如果给定的值是a,则
Promise.resolve
返回相同的引用承诺。当你想检查一个承诺是否相等时,这可能是一个问题和async函数的返回值。
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