Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. I thought it was doing an http request.

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?

like image 699
skellertor Avatar asked Nov 02 '18 05:11

skellertor


People also ask

What happens if you await a synchronous function?

Await is in an async function to ensure that all promises that are returned in the function are synchronized. With async/await, there's no use of callbacks. try and catch methods are also used to get rejection values of async functions.

Does await return a value?

Await expressions make promise-returning functions behave as though they're synchronous by suspending execution until the returned promise is fulfilled or rejected. The resolved value of the promise is treated as the return value of the await expression.

Do async functions run synchronously?

Synchronous code inside an async function runs synchronously. The interpreter will only move on to the next line after the call of the async function (here, the console. log("b"); ) after all synchronous code has finished - for example, if it runs into an await .

What is the difference between Sync and await?

The differences between asynchronous and synchronous include: Async is multi-thread, which means operations or programs can run in parallel. Sync is single-thread, so only one operation or program will run at a time. Async is non-blocking, which means it will send multiple requests to a server.


2 Answers

It worked because await does not require its operand to be a promise! It returns the value of the awaited expression if it is not a promise.

See the documentation for the await operator

The important part is:

[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.

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.

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. 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! So the await did have an effect. If you did not put the await there, then you would have seen "Finishing g" before "Finishing the script". 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. 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.

like image 94
Ray Toal Avatar answered Oct 31 '22 01:10

Ray Toal


If you await a value that is not a promise, it is converted to a resolved promise by using Promise.resolve.

function sync(){
	return 1
}

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

(async ()=>{
  const v = await Promise.resolve(sync()); console.log(v)
})()
like image 24
Anurag Awasthi Avatar answered Oct 31 '22 01:10

Anurag Awasthi