等待同步功能是否会同步返回值?

时间:2018-11-02 05:51:14

标签: javascript async-await

我从一个我不熟悉的内部实用程序库中导入了一个函数。该库没有任何文档,由于其名称getUserDetails,我只是假设它是异步的。我以为它正在执行http请求。

我在这样的异步函数中使用了它

async function getAllUserInfo(event) {
    const details = await getUserDetails(event);
    // other stuff
}

我的假设是错误的。一位同事指出这不是异步的。我最终更改了它,但是当我使用不正确时,它仍然可以工作。我能够等待一个同步函数,它返回了正确的数据。

我的问题是关于它是如何工作的。在同步函数上加前缀和等待是否会使它在下一个滴答声中解析,还是像同步函数一样立即返回?

2 个答案:

答案 0 :(得分:2)

之所以起作用,是因为await不需要将其操作数作为承诺!如果不是promise,它将返回等待的表达式的值。

请参见the documentation for the await operator

重要的部分是:

[rv] = await expression; 

expression
    A Promise or any value to wait for.
rv
    Returns the fulfilled value of the promise, or the value itself if it's not a Promise.

在您的情况下,getUserDetails没有返回承诺,而是返回了一些常规用户详细信息,因此await表达式仅返回了这些详细信息,就像操作员根本不在那儿一样。

但是,即使getUserDetails是同步的,在异步函数中在其前面加上await也会放弃对其调用者的控制,而在调用函数之后的“回调部分” await 。这是一个示例脚本:

function f() {
  console.log('In f');
}

async function g() {
  console.log('Starting g');
  await f();
  console.log('Finishing g');
}

console.log('Starting the script')
g();
console.log('Finishing the script')

注意脚本的输出:

$ node asynctest.js 
Starting the script
Starting g
In f
Finishing the script
Finishing g

请注意await如何调用“暂停” g,直到主块完成后才能恢复!因此await did 会起作用。如果您没有在这里等待,那么您将在“完成脚本”之前看到“ Finishing g”。试试吧!

顺便说一句,这样做的原因是,即使可以为await提供一个不会产生承诺的表达式,JS也会将非承诺操作数转换为立即解析为该值的承诺。因此,仍然会创建一个Promise,将等待后的部分视为回调,直到当前执行流程完成后才能运行。

答案 1 :(得分:1)

如果您等待的不是承诺值,则可以使用Promise.resolve将其转换为已解决的承诺。

function sync(){
	return 1
}

(async ()=>{
  const v = await sync(); console.log(v)
})();

(async ()=>{
  const v = await Promise.resolve(sync()); console.log(v)
})()