【问题标题】:Does awaiting a synchronous function synchronously return a value?等待同步函数是否同步返回值?
【发布时间】:2019-04-06 09:15:41
【问题描述】:

我从一个我不熟悉的内部实用程序库中导入了一个函数。这个库没有文档,我只是假设它是异步的,因为它的名字getUserDetails。我以为它在做一个http请求。

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

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

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

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

【问题讨论】:

    标签: javascript async-await


    【解决方案1】:

    之所以有效,是因为await 不需要它的操作数是一个承诺!如果它不是一个promise,它会返回等待的表达式的值。

    the documentation for the await operator

    重要的部分是:

    [rv] = await expression;
    
    • expressionPromise 或任何等待的值。
    • rv:返回 promise 的已实现值,如果不是 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 确实有效果。如果您没有将 await 放在那里,那么您会在“完成脚本”之前看到“完成 g”。试试看!

    顺便说一句,产生这种效果的原因是即使await 可以被赋予一个不产生承诺的表达式,JS 也会将一个非承诺操作数变成一个立即解析为该值的承诺。所以仍然会创建一个promise,并且将await之后的部分视为回调,直到当前执行流程结束才能运行。

    【讨论】:

    • 有趣。感谢您将我指向文档。我最初错过了If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise. 这行,所以如果我理解正确,如果同步函数前面带有await,它会异步返回值。
    • 同意,非常好。我已经详细说明了我的答案,并包含了一个您可以运行的示例。希望它能把事情弄清楚。如果没有,请告诉我,我会再试一次。
    • 完美。谢谢!
    【解决方案2】:

    如果您 await 一个不是 Promise 的值,则会使用 Promise.resolve 将其转换为已解决的 Promise。

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

    【讨论】:

      猜你喜欢
      • 2017-09-24
      • 1970-01-01
      • 1970-01-01
      • 2023-02-10
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-07
      相关资源
      最近更新 更多