我应该定义异步函数,如果我显式返回一个承诺?



我们知道async函数隐式返回一个Promise。但我有一个纯粹迂腐的问题。我应该把async关键字,如果我返回一个承诺显式?

:

const wait = async ms => new Promise(
resolve => setTimeout(resolve, ms)
);

和这个有什么不同吗?

const wait = ms => new Promise(
resolve => setTimeout(resolve, ms)
);

我相信在技术上它们是相同的。在这两种定义这类函数的方法背后有什么风格指南或官方推荐吗?

我认为使用async函数有四个主要原因:

  1. 您要使用await
  2. 你想让它自动捕捉同步异常,并把它们变成一个被拒绝的承诺。
  3. 你希望它总是返回一个承诺,不管你的函数实际返回什么。
  4. 你喜欢这样一个事实,即使函数async使查看代码的调用者清楚地知道函数总是返回一个承诺-本质上是自我记录。

所以,如果你不使用await,你不需要第2点,你已经手动返回一个承诺,那么真的没有必要将函数声明为async


关于以上几点的几点思考。

如果你打算使用await,第1点需要async。没有别的办法了。

第2点和第3点实际上只是编程方便。如果你捕获自己的同步异常,或者确定没有同步异常,并且控制所有代码路径返回承诺,那么async是不必要的。

如果您的代码同时具有同步代码路径和异步代码路径,则会出现第2点和第3点,例如检查缓存并返回缓存中存在的值,如果不在缓存中,则发出网络请求以获取该值。如上所述,这可以在没有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

相关内容

  • 没有找到相关文章

最新更新