为什么在具有await关键字的函数中必须加入async关键字?

7

我只想等待一个进程完成,而不想让函数异步化。
看下面的代码。
因为函数中有一个await关键字,所以我不得不将getUserList变成了异步函数。因此,我还必须像"await UsersService.getUserList"这样编写代码来执行该方法,并且我还必须将父函数变成异步函数。但这不是我想要的。

import xr from 'xr' //a package for http requests

class UsersService {

  static async getUserList() {
    const res = await xr.get('http://localhost/api/users')
    return res.data
  }

}

export default UsersService

import UsersService from './UsersService'

class SomeClass {

  async someFunction() { //async again!!
    const users = await UsersService.getUserList() //await again!!
  }

}

因为没有使用async,所以该函数是同步的,因此它保证会完成其主体执行并返回结果。 - zerkms
还有,我不得不将父函数改为异步的——你可以使用 Promise 替代。 - zerkms
//再次等待!!如果是异步的,你需要等待它完成。 - zerkms
await 的意思是同步的,所以 getUserList 方法对我来说应该是同步的。 - Nigiri
我理解使用 Promise 可以使得 getUserList 同步化。 - Nigiri
1
"await的意思是同步的,所以getUserList方法对我来说应该是同步的" - 不是这样,它的意思是“我们正在异步地调用一个函数并成为异步的,因为我们需要等待结果”。 - zerkms
1个回答

10

这是一个设计选择吗?

这是因为JavaScript的同步性质。如果你想让一个函数以同步方式运行异步命令,它会阻塞整个程序,这是非常不可取的,如果是在客户端会很糟糕,在服务器端更是如此。因此,async 函数就出现了。这些函数从正常流程中分离出来,这也是 await 起作用的原因。

为什么要这样做?

另一个原因是,await+async 是Promise的语法糖。Promise是异步的,你无法停止它。这意味着 await不能将异步函数变为同步,它只是等待这个异步函数完成后才继续执行后面的代码。如果它真的阻塞了整个事件循环,那么想象一下,如果你想创建一个应用程序,在客户端之间发送数据,每次进行异步请求时,整个服务器应用程序都会挂起,而不只是使单个请求异步。

所以这样想:

你不是让异步函数变成同步函数,而是让程序的其他部分异步地去处理它。

因此,不要认为 asyncawait 的先决条件,而是把它们组合在一起 (async+await),因为这就是它们的基本工作方式。如果你想了解更多关于异步和await的知识,我强烈推荐阅读我的博客文章,其中深入探讨了这个问题。


2
你正在将程序的其余部分异步化以应对它。我终于明白了!谢谢! - Nigiri
1
你的博客已经宕机了。 - Ryan White
这是否意味着,如果我使用了一次 async,那么我必须将每一个使用该函数的函数都设为 async? - windmaomao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接