- Understanding Asynchronous JavaScript
- What is async?
- What is await?
- Key Differences Between async and await
- Practical Examples
- Error Handling with async and await
- Differences in Performance
JavaScript has evolved significantly over the years, especially in the way it handles asynchronous operations. Among the most notable advancements are the async
and await
keywords, introduced in ECMAScript 2017. These keywords simplify working with promises, making asynchronous code more readable and easier to write. In this article, we'll delve into the differences between async
and await
, how they work together, and their individual roles in handling asynchronous operations.
For more detailed information, refer to the official documentation:
Understanding Asynchronous JavaScript
Before we dive into async
and await
, let's briefly review asynchronous programming in JavaScript. JavaScript is single-threaded, meaning it can execute only one task at a time. Asynchronous programming allows JavaScript to perform long-running tasks, like fetching data from a server, without blocking the main thread. This is achieved using callbacks, promises, and, more recently, async
/await
.
async
?
What is The async
keyword is used to define an asynchronous function. An async
function always returns a promise, and the promise's resolved value is the value returned by the function. If the function throws an error, the promise is rejected with that error.
async
Function
Defining an Here's how you define an async
function:
async function fetchData() {
return 'Data fetched';
}
In this example, fetchData
is an asynchronous function that returns a promise. The promise resolves with the value 'Data fetched'
.
async
Functions
Handling Errors in Errors in async
functions can be handled using try...catch
blocks:
async function fetchData() {
try {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
}
}
In this example, if an error occurs during the fetch operation, it is caught by the catch
block.
await
?
What is The await
keyword is used inside an async
function to pause the execution of the function until a promise is resolved or rejected. It can only be used within an async
function.
await
Using Here’s how you use await
:
async function fetchData() {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
return data;
}
In this example, the await
keyword pauses the execution of fetchData
until the fetch
promise is resolved. Once resolved, the response is passed to response.json()
, which is also awaited until it resolves.
async
and await
Key Differences Between While async
and await
are used together, they serve different purposes. Here are the key differences:
-
Purpose:
-
async
: Defines an asynchronous function and ensures it returns a promise. -
await
: Pauses the execution of anasync
function until the promise is resolved.
-
-
Usage:
-
async
: Used to declare a function as asynchronous. -
await
: Used to wait for a promise to resolve or reject within anasync
function.
-
-
Return Value:
-
async
: Always returns a promise. -
await
: Returns the resolved value of the promise or throws an error if the promise is rejected.
-
Practical Examples
Let's explore some practical examples to see how async
and await
work together.
Fetching Data from an API
Consider an example where we fetch data from an API:
async function getData() {
try {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
getData();
In this example, getData
is an async
function that uses await
to wait for the fetch operation and the JSON parsing to complete. The try...catch
block handles any errors that might occur during these operations.
Parallel Asynchronous Operations
You can use Promise.all
to run multiple asynchronous operations in parallel:
async function getMultipleData() {
try {
let [response1, response2] = await Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2')
]);
let data1 = await response1.json();
let data2 = await response2.json();
console.log(data1, data2);
} catch (error) {
console.error('Error fetching data:', error);
}
}
getMultipleData();
In this example, Promise.all
is used to wait for both fetch operations to complete before proceeding. This approach is more efficient than awaiting each fetch individually.
async
and await
Error Handling with Handling errors in asynchronous code is crucial for robust applications. With async
and await
, you can use try...catch
blocks for error handling, making the code cleaner and more readable compared to traditional promise chaining.
Example of Error Handling
async function fetchDataWithErrorHandling() {
try {
let response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Network response was not ok');
}
let data = await response.json();
return data;
} catch (error) {
console.error('Fetching data failed:', error);
throw error; // Re-throw the error if needed
}
}
fetchDataWithErrorHandling()
.then(data => console.log(data))
.catch(error => console.error('Error in fetchDataWithErrorHandling:', error));
In this example, if the fetch fails or the response is not OK, an error is thrown and caught in the catch
block. The error is also re-thrown to be handled by any further .catch
blocks in the promise chain.
Differences in Performance
While async
and await
simplify the code, it's important to understand their impact on performance. Using await
within a loop, for example, can lead to sequential execution, which might not be efficient. Instead, you can use Promise.all
for parallel execution.
Sequential Execution Example
async function fetchSequential(urls) {
for (let url of urls) {
let response = await fetch(url);
let data = await response.json();
console.log(data);
}
}
Parallel Execution Example
async function fetchParallel(urls) {
let promises = urls.map(url => fetch(url).then(response => response.json()));
let results = await Promise.all(promises);
results.forEach(data => console.log(data));
}
In the parallel execution example, all fetch operations start at the same time, significantly improving performance when dealing with multiple asynchronous tasks.
Interested in proving your knowledge of this topic? Take the JavaScript Fundamentals certification.
JavaScript Fundamentals
Showcase your knowledge of JavaScript in this exam, featuring questions on the language, syntax and features.
$99
![JavaScript Fundamentals](/img/badges/javascript-fundamentals.png)