Have you ever wondered why some websites seem to load new content seamlessly, while you continue to interact with other parts of the site? Think about when you're scrolling through your social media feed and new posts appear almost by magic, without having to refresh the page. This level of interactivity and responsiveness is due in large part to the power of asynchronous JavaScript.journey into the world of asynchronous programming!
In this lesson, you'll get to grips with the concept of asynchronous programming.
Asynchronous JavaScript
As you learned in the Introduction to Events lesson, we just don't know exactly when certain things will happen. We don't know when a user will click a button. When we send a request across the internet for data, we don't know when the response will come back.
Clearly, waiting for these events to happen before moving on to the next line of code would be inefficient. This is where asynchronous programming comes in. This is a powerful concept, and one that is fundamental to programming in JavaScript.
Asynchronous operations in JavaScript are like sending a letter and then going about your day. You don't wait by the mailbox for a response; instead, you carry on with other work, giving you the chance to perform tasks without blocking the execution.
Eventually, the reply comes, and you deal with it then.
This doesn't mean that JavaScript is capable of doing two things at the same time. It's not. It's single-threaded. It just means that JavaScript makes use of queues and event loops to handle asynchronous operations. Theses structures are provided by the runtime, which is the browser (or another environment, like Node.js).
Said in another way, while JavaScript is single-threaded, the environment in which it runs is not. The browser is a concurrent application, and it's the browser that augments JavaScript, facilitating asynchronous operations.
You'll not cover the details of how this works in this course, but you will dive into it deeper in the following course.
JavaScript's design inherently embraces asynchronicity. By leveraging callbacks, promises, and async/await patterns, JavaScript handles asynchronous operations, ensuring that you can smoothly manage tasks like data requests, processing user interactions, and updating the UI without "freezing".
How to Leverage Asynchronous JavaScript with Requests
There are three ways to leverage asynchronous JavaScript when making requests that you will cover in the coming sections:
- With callbacks - using the
XMLHttpRequest() - With promises - using
fetch() - With
async/await- using theasyncandawaitsyntax which allows a nicer syntax for promise based code
All three aren't all that different in that they all allow you to tap into asynchronous JavaScript. The difference is in the syntax.
Example: The setTimeOut Method
A good basic example of some asynchronous code is the Native JavaScript method you used in the introductory example of this course, setTimeout(). Remember it? This method is asynchronous: the function to be run, the callback function, is placed in memory and will not run until at least the specified time has passed. Meanwhile, if other instructions can run, they will run.
console.log(1);
setTimeout(() => console.log(2), 500); // wait 500 ms
console.log(3);
// OUTPUT
1;
3;
2;
If setTimeout() ran synchronously, the numbers 1, 2 and 3 would be logged in order. But, since setTimeout() is asynchronous, the function that performs the console.log of the number 2 is handed over to the browser until 500ms has passed, after which, the browser puts the function into a queue for JavaScript to execute as soon as possible.
How Does Your Browser Execute Javascript
JS is single threaded, it will do one task at a time and not do anything else until that is done. To prove this, try this experiment:
- Go to any webpage with a lot of functionality like Google or YouTube or Facebook.
- Bring up the console in developer tools on this website.
- Now to break it, type this into the console:
while (true) {}
Try clicking buttons on the page, you cant? Thats right, JavaScript is diligently doing what you told it to do. It will stay in that while loop until true is false, until night is day, until the sun sets in the east and rises in the west...you get the idea.
Ok, right click on the window bar or the menu, search for the chrome "task manager". Find the offending tab and shut it down.
You may have noticed that it was only this single tab that gave you problems. This is because modern browsers typically use separate JavaScript threads per tab, or domain. Chrome, for example, implements process-per-site policy.
The way JavaScript gets around it's single threaded nature is by using asynchronous mechanisms. So instead of having to wait for a task to finish before moving on to the next one, it can put that task in a queue and move on to the next task. When the task is done, it will be placed in another queue by the browser, so that the JavaScript thread can get around to executing it as soon as possible.
How Do Asynchronous Web APIs and Callbacks Work
The setTimeout API, and others, are known as Web APIs, since they don't form part of the official ECMA spec. That is, while they go hand in hand with JavaScript, the language is standardized by ECMA, the Web APIs are maintained by different standards bodies, like the W3C.
Web APIs like fetch() are asynchronous. You can ask them to do something and then to do something else once the first part is done. When doing this you have to provide a callback function. Once the request is done, the callback is placed in a queue to run "as soon as possible". This is to say, it will run when the JavaScript thread has finished what it is currently doing.
There is too much to go into here, but for a great visualization of what is happening when a setTimeout() function is called, check out this great visualization of all this, loupe.
## Some Technical Jargon
In JavaScript, each running environment (like a browser tab) usually has its own main execution thread. This thread works with a stack and a heap. The stack is where the script’s actual execution takes place, handling things like function calls and control flow. Meanwhile, the heap is more like a memory pool where all the objects and variables get stored.
Besides these, there's also an event loop and a callback queue in each thread. The event loop keeps checking the callback queue (sometimes called the message or task queue) to see if there's anything that needs running, like events that have fired or asynchronous tasks that have completed. So, in simple terms, think of it like this: the stack is where the immediate action happens, the heap is like a storage space, and the event loop with its callback queue manages tasks that are lined up waiting for their turn to get onto the stack.
It's the browser that's constantly listening for events, managing those heaps and stacks, and deciding when to queue up tasks and callbacks. Essentially, the browser is the stage and the conductor for your JavaScript code, making sure everything runs smoothly, events are handled in order, and your script interacts seamlessly with the web page and the user.
Summary: Synchronous to Asynchronous - Javascript Callback, Promise and Async Functions
You've taken a deep dive into the mechanisms that make websites dynamic and interactive without interrupting user experience. You've
- Grasped the concept of asynchronous programming in JavaScript, likening it to sending a letter and not waiting by the mailbox for a response. Instead, continuing with other activities.
- Discovered that JavaScript is single-threaded but operates within a concurrent environment like a browser which deals with async tasks using queues and event loops.
- Understood the concept with a simple
setTimeout()function example, which defers the execution of its callback to allow the JavaScript thread to run subsequent code.
In essence, it's these asynchronous patterns and JavaScript's utilization of the browser's multi-threaded abilities that keep our web pages alive with activity without us having to twiddle our thumbs while we wait for a response.