2

I am aiming to understand what exactly is it about certain JavaScript functions that make them asynchronous. You could have a function like this:

function someRandomFunction () {
  for (let i of everything) {
    iterator++
    something = true
    hello = that + whatever
  }
}

Nothing about this function is asynchronous. It does a lot of stuff but it does it very quickly.

But then take a Node.js function like this:

fs.readFile('path/to/file', (err, data) => {
  // do something
})

This function is declared to be asynchronous. But why is it? What is the reason behind it?

Is it because it takes a certain amount of time for reading a file to complete, therefore it's asynchronous? Why is that asynchronous when looping through some variables and doing some calculations is not asynchronous?

4
  • Have you come across this thread talking about the function? stackoverflow.com/questions/10058814/get-data-from-fs-readfile Commented Apr 26, 2018 at 19:25
  • See How do you create custom asynchronous functions and maybe How do I know which callbacks are asynchronous? Commented Apr 26, 2018 at 19:34
  • So, without hijacking the pretty good answer down below, I wanted to add: Synchronous code = I assembled a pizza, put it into the oven, watched the oven for 20 minutes as the pizza slowly cooked, then had my pizza. Asynchronous code = I assembled the pizza, put it into the oven, went and did something else for 20 minutes, then 20 minutes later the pizza was cooked. Async really boils down to "I don't know when this code will finish, and I do not have direct control of it. Let me know when it is done." Something to note -- that code CAN be fast. Commented Apr 26, 2018 at 19:34
  • Javascript is a single threaded runtime, only one thing can run at a time. In Node (and browsers) asynchronous operations are delegated to the event loop, while synchronous operations remain on the stack. Check out this YouTube video, it may help you understand what is going on: Philip Roberts: What the heck is the event loop anyway? Commented Apr 26, 2018 at 19:37

4 Answers 4

5

The 'idea' of something being asynchronous means "we've relinquished control to some other operational code, and we have no idea when that other code will allow us to operate again".

So in your bottom sample, you give control over to node's filesystem operations to read a file. We don't know how large that file is, so there is no way to anticipate how much time it will take to complete. So JavaScript allows us to provide a "callback" that get's fired when the async operation is complete. When the callback is executed, control is returned to our code.

The top example is synchronous because your code maintains control over the operation and Javascript executes code synchronously by nature.

Sign up to request clarification or add additional context in comments.

4 Comments

What you describe sounds like coroutines. In JS, all calls to functions that do some asynchronous work still do return immediately.
Of course, that is the synchronous nature of JS that I described. I suppose in an effort to keep this less pedantic I'll offend the deeply knowledgable. Sorry Bergi.
@Bergi - in addition, I'm fairly certain that fs.readFile() returns undefined
I like this explanation: "we've relinquished control to some other operational code, and we have no idea when that other code will allow us to operate again"
2

A function is either explicitly synchronous or asynchronous; there's no "certain amount of time" that automatically makes it asynchronous.

The important thing to remember with Node is that it's "async I/O", which means nothing is ever async without some input/output to/from the process. You normally see this with file reading/writing, database calls, and anything that requires a network call.

Comments

2

This is a basic but fundamental question. Passing a function to another function doesn't make the code asynchronous automatically. It's all about attemting to work with another piece of code, mostly of unknown origins, probably but not necessarily related with operating system's IO mechanism. In another words you ask something to happen out of the realm of the currently exectuing JS context by handing a task to known or unknown resources which are possibly running on a separate thread.

As i said this can be an IO operation or a database access of which you have no idea on

  • What code is running
  • At which thread it is running
  • How long it will take
  • Whether it will succeed or not

Behind the curtains these alien codes finally trigger the event queue to invoke the callback function through a driver. In some pure functional languages like Haskell such activities are strictly kept away from the context and must be handled by monadic type functions. In JS this is basically done by asynchronous workflow by callbacks, promises or async-awiat mechanism.

Once you hand out a task to the outer world then there shall be no way for it to interfere with your synchronous code.

Comments

1

In terms of JavaScript, the difference between synchronous and async functions is where and when the code is executed. Synchronous functions are executed immediately one after the other in the current call stack. Async functions are passed off to the event loop, and values returned once the current call stack has completed execution.

Caveat being, nothing in JavaScript is truly asynchronous due to the fact that JS only executes on a single process thread

5 Comments

Async functions are passed off to the event loop, and values returned once the current call stack has completed execution. Returned by whom in the first place..?
The event callback que pushes it back into the call stack. This page does a great job visualizing how it works: latentflip.com/loupe
Yes but how exactly the result arises and from where it originates? Event queue is just an observer to invoke the callback with obtained data not the source of the result. Asynchronous workflow abstraction has much more to it than just the event queue.
What determines if a function needs to be passed to the event loop? That is the core of my question I think.
@JakeWilson that is determined by whomever is writing the program. In your example 'fs' would potentially be reading from a large file, if the function were synchronous it would end up blocking your entire call stack until the file had been fully read, likely causing noticable performance issues for the end user. It all depends on the use case and the estimated run time of the function. Alternatively, you can force a loop to be asynchronous as well

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.