我们知道
async
函数隐式返回 Promise。但我有一个纯粹迂腐的问题。如果我显式返回 Promise,我应该添加 async
关键字吗?
是这个吗:
const wait = async ms => new Promise(
resolve => setTimeout(resolve, ms)
);
与此有什么不同吗?
const wait = ms => new Promise(
resolve => setTimeout(resolve, ms)
);
我相信从技术上来说它们是相同的。这两种定义这种函数的方法背后是否有任何风格指南或官方推荐?
我认为使用
async
函数有四个主要原因:
await
。为了使用 await
,包含 await
的函数必须标记为 async
。async
可以让查看代码的调用者清楚地知道该函数始终返回一个承诺 - 本质上是自我记录。因此,如果您不使用
await
并且不需要第 2 点,并且您已经手动返回承诺,那么实际上不需要将函数声明为 async
。
对以上几点还有一些想法。
如果您要使用async
,则第 1 点需要
await
。没有其他办法可以解决这个问题。
第 #2 点和第 #3 点实际上只是为了编程方便。如果您捕获自己的同步异常或确定不存在同步异常并且您正在控制所有代码路径以返回 Promise,则不需要
async
。
如果您的代码同时具有同步代码路径和异步代码路径,则可能会出现#2 和 #3 点,例如检查缓存并返回一个值(如果该值存在于缓存中),如果不存在于缓存中,则返回获取值的网络请求。如上所述,这可以在没有
async
的情况下手动编码,但有时使用 async
代码会更简单一些,因为它会自动捕获同步异常并自动将返回值包装在 Promise 中。
第 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
关键字的变体。
注:
即使异步函数的返回值的行为就像 包裹在
Promise.resolve
中,它们不等价。异步函数将返回不同的引用,而 如果给定值是a,则
Promise.resolve
返回相同的引用 承诺。当你想检查 Promise 的相等性时,这可能是一个问题 以及异步函数的返回值。
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