When you look at the second hand of a ticking clock, you’ll find out that the second hand moves sequentially. It points at 1 before it does 2, and then 3. It does not point at 4 and then 1 and then 9.
Now imagine that the second hand is the JavaScript runtime and each number is a function. The second hand, which is our imaginary JavaScript runtime, determines what function runs by pointing at the number. When it points at 1, function 1 runs and when it points at 2, function 2 runs. When it points at 3 and function 3 says You’ve asked me to run and I will, but I will not run completely now. Go ahead and ask the statements after me to run. I’ll be done running at a future time and I will notify you when I’m done running, then function 3 is an asynchronous function. When function 3 is done running, it notifies the second hand. When the second hand is done handling all synchronous functions/statements, it goes to function 3 to do whatever should be done after function 3 has run.
Callback functions are usually attached to asynchronous functions so that when the asynchronous function returns with a value, the callback function would accept the value and run with the value. Definitely not the Hussein Bolt type of running, but if you think of it that way, consider “value” to be the baton in a relay race 😉.
Real life examples
It would make more sense help to add practical use cases of asynchronous functions.
setTimeout
setTimeout
is an asynchronous function that JavaScript can access. When
setTimeout
is run with a function f
and a number n
passed in, it runs
completely after n
milliseconds after which it releases f
to be run by the
JavaScript runtime. It does not run completely after it has been asked to run by
the JavaScript runtime when it was called. It says to the JavaScript runtime Go
ahead and run other statements after me. I’ll notify you after I’m done
running. After n
milliseconds, it notifies the JavaScript runtime that it is
done running and passes f
to it so that f
will be run when the JavaScript
runtime is ready. f
runs approximately 1 after n
millliseconds.
console.log(1);
console.log(2);
setTimeout(() => {
console.log("I am function f");
}, 0);
console.log(3);
fetch
According to MDN docs, “the fetch
API provides an interface for fetching
resources”. In programming, fetching resources (JSON, images, files) across a
network is an I/O operation. I/O operations do not have a predictable completion
time. They could be held back by anything - poor network, low computer speed,
the resource server taking longer to respond, anything. fetch
is an
asynchronous function. It runs completely at a later time. How does fetch work?
When fetch
is called to run by the JavaScript runtime, it immediately returns
a promise. See “promise” as an empty gift box with two partitions. fetch
says
to the runtime I’ve been called to run, and I will. Go ahead and run other
statements after me, but hold this empty gift box for now. When I’m done
running, whatever value I get, I’ll place it in the box and notify you. If I run
completely without any error, I’ll pass the value I return with into partition
one. If there are any errors, I’ll pass the error into partition two. For a
five-letter function name, I think that’s a lot of talking.
Partition one is the function called then
and you guessed right, catch
is
partition two. We pass functions into then
and catch
so that whenever
fetch
returns with a value, the functions we passed into then
or catch
will run with the value passed into them.
Is JavaScript an Asynchronous Programming Language?
No. JavaScript is not an asynchronous programming language. So what are
setTimeout
and fetch
?. Well, technically, these functions are not JavaScript
functions. Both are attached to the window
and global
objects in the browser
and Node.js. These functions are abstractions.
Think of a door handle. As a user of the door handle, you do not have to know
what happens inside the door handle that makes it open the door when you pull
it. All you have to do is pull the handle a certain way and the door is opened.
You, the puller of the door handle, are different from the door handle. You do
not own the mechanism for opening the door. You only use it through the handle.
JavaScript too is like you, and these functions are like the door handle. All
JavaScript has to do is call these functions and the real deal starts to work in
the programming language that the window
or the global
object was written
in.
To make it clearer, here’s another example: addEventListener
.
addEventListener
is not a JavaScript function or method. It is attached to the
DOM. If addEventListener
were a JavaScript method, it will exist everywhere
that JavaScript exists, including Node.js; but it doesn’t exist in Node.js.
Conclusion
There you have it. An asynchronous function is one that completely runs at a later time and will not prevent the statements that are to run after it from running. It will notify the JavaScript runtime after it is done running for the JavaScript runtime to take action. This behaviour is different from a long-running Fibonacci function which is synchronous and will prevent the functions after it from running until it runs completely.
People illustrations by Storyset
approximately because the JavaScript runtime will run all synchronous functions to completion before running
f
, even aftern
milliseconds has elapsed. ↩︎