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?

Jake Wilson
  • 88,616
  • 93
  • 252
  • 370
  • Have you come across this thread talking about the function? https://stackoverflow.com/questions/10058814/get-data-from-fs-readfile – chevybow Apr 26 '18 at 19:25
  • See [How do you create custom asynchronous functions](https://stackoverflow.com/q/22286887/1048572) and maybe [How do I know which callbacks are asynchronous?](https://stackoverflow.com/q/19083357/1048572) – Bergi Apr 26 '18 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. – MikeJannino Apr 26 '18 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?](https://www.youtube.com/watch?v=8aGhZQkoFbQ) – Jake Holzinger Apr 26 '18 at 19:37

4 Answers4

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.

Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
  • What you describe sounds like coroutines. In JS, all calls to functions that do some asynchronous work still do return immediately. – Bergi Apr 26 '18 at 19:40
  • 2
    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. – Randy Casburn Apr 26 '18 at 19:42
  • @Bergi - in addition, I'm fairly certain that `fs.readFile()` returns `undefined` – Randy Casburn Apr 26 '18 at 19:44
  • 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" – Jake Wilson Apr 26 '18 at 22:54
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.

David
  • 197
  • 7
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.

Redu
  • 25,060
  • 6
  • 56
  • 76
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

Vinnie James
  • 5,763
  • 6
  • 43
  • 52
  • **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..? – Redu Apr 26 '18 at 21:53
  • The event callback que pushes it back into the call stack. This page does a great job visualizing how it works: http://latentflip.com/loupe – Vinnie James Apr 26 '18 at 21:57
  • 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. – Redu Apr 26 '18 at 22:02
  • What determines if a function needs to be passed to the event loop? That is the core of my question I think. – Jake Wilson Apr 26 '18 at 22:54
  • @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 – Vinnie James Apr 27 '18 at 03:03