简体   繁体   English

等待同步函数是否同步返回值?

[英]Does awaiting a synchronous function synchronously return a value?

I imported a function from an internal utility library that I am unfamiliar with.我从一个我不熟悉的内部实用程序库中导入了一个函数。 There is no documentation for this library and I just assumed it was asynchronous due to its name getUserDetails .这个库没有文档,我只是假设它是异步的,因为它的名字是getUserDetails I thought it was doing an http request.我以为它在做一个http请求。

I used it in an async function like this我在这样的异步函数中使用它

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

I was wrong in my assumption.我的假设是错误的。 A co-worker pointed out that is was not asynchronous.一位同事指出这不是异步的。 I ended up changing it, but when I was using it incorrectly it still worked.我最终改变了它,但是当我错误地使用它时它仍然有效。 I was able to await a synchronous function and it returned the correct data.我能够等待同步函数并返回正确的数据。

My question is in regards to how it worked.我的问题是关于它是如何工作的。 Does prepending an await on a synchronous function make it resolve on the next tick, or does it return immediately like a synchronous function should?是否在同步函数上添加 await 使其在下一个滴答声中解析,还是像同步函数那样立即返回?

It worked because await does not require its operand to be a promise!它起作用是因为await不需要它的操作数是一个承诺! It returns the value of the awaited expression if it is not a promise.如果它不是承诺,则返回等待表达式的值。

See the documentation for the await operator请参阅await 运算符的文档

The important part is:重要的部分是:

 [rv] = await expression;
  • expression : A Promise or any value to wait for. expression : 一个Promise或任何要等待的值。
  • rv : Returns the fulfilled value of the promise, or the value itself if it's not a Promise . rv :返回 promise 的已履行值,如果它不是Promise则返回值本身。

In your case getUserDetails did not return a promise, but rather some regular user details, so the await expression just returned those details, just as if the operator was not there at all.在您的情况下, getUserDetails没有返回承诺,而是一些常规用户详细信息,因此await表达式仅返回这些详细信息,就好像操作员根本不在那里一样。

However , even though getUserDetails is synchronous, preceding it with await in your async function will give up control to its caller, and the "callback portion" after the await is picked up later.但是,即使getUserDetails是同步的,在 async 函数中在它前面加上await将放弃对其调用者的控制,并且稍后选择await之后的“回调部分”。 Here is an example script:这是一个示例脚本:

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')

Notice the output of the script:注意脚本的输出:

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

Notice how the await call "paused" g, which was not able to resume until the main block finished!注意await调用如何“暂停” g,直到主块完成才能恢复! So the await did have an effect.所以await确实有效果。 If you did not put the await there, then you would have seen "Finishing g" before "Finishing the script".如果您没有将等待放在那里,那么您会在“完成脚本”之前看到“完成 g”。 Try it out!试试看!

BTW the reason for the effect is that even though await can be given an expression that does not produce a promise, JS will turn a non-promise operand into a promise immediately resolved to that value.顺便说一句,效果的原因是,即使可以给await一个不产生承诺的表达式,JS 也会将非承诺操作数转换为立即解析为该值的承诺。 So a promise is still created and the part after await is treated as a callback, which cannot be run until the current execution flow finishes.所以仍然创建了一个promise,await之后的部分被视为回调,在当前执行流程完成之前不能运行。

If you await a value that is not a promise, it is converted to a resolved promise by using Promise.resolve .如果您等待一个不是承诺的值,它会通过使用Promise.resolve转换为已解决的承诺。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM