Introduction to Asynchronous JavaScript
JavaScript is single-threaded, meaning it can only execute one task at a time. To handle multiple tasks, especially I/O operations like API requests or file reading, JavaScript uses asynchronous programming. This allows other tasks to continue running while waiting for the completion of long-running operations.
Callback Functions
Initially, asynchronous tasks in JavaScript were handled using callback functions. A callback is a function passed into another function as an argument, which is then executed after the completion of the operation.
Example:
function fetchData(callback) {
setTimeout(() => {
callback('Data fetched');
}, 2000);
}
fetchData((message) => {
console.log(message);
});
Promises
Promises were introduced to handle asynchronous operations more effectively. A Promise represents a value which may be available now, or in the future, or never.
Example:
let promise = new [Promise]((resolve, reject) => {
setTimeout(() => {
resolve('Data fetched');
}, 2000);
});
promise.then((message) => {
console.log(message);
}).catch((error) => {
console.error(error);
});
Async/Await
Async/Await is a syntactic sugar built on top of Promises, making asynchronous code look and behave like synchronous code. This makes the code easier to read and understand.
Basic Usage
-
Async Function: A function declared with the
async
keyword returns a Promise. -
Await Keyword: The
await
keyword can only be used inside anasync
function. It makes JavaScript wait until the Promise is resolved or rejected.
Example:
async function fetchData() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('Data fetched'), 2000);
});
let result = await promise; // Wait until the promise resolves
console.log(result);
}
fetchData();
Error Handling
With async/await
, error handling becomes straightforward using try...catch
blocks.
Example:
async function fetchData() {
try {
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject('Error fetching data'), 2000);
});
let result = await promise;
console.log(result);
} catch (error) {
console.error(error);
}
}
fetchData();
Parallel Execution
To execute multiple asynchronous operations in parallel, Promise.all
can be used with async/await
.
Example:
async function fetchAllData() {
let promise1 = new Promise((resolve) => setTimeout(() => resolve('Data 1'), 2000));
let promise2 = new Promise((resolve) => setTimeout(() => resolve('Data 2'), 1000));
let results = await Promise.all([promise1, promise2]);
console.log(results); // ['Data 1', 'Data 2']
}
fetchAllData();
Advanced Concepts
Sequential Execution
If tasks need to be executed sequentially, use await
one after another.
Example:
async function fetchSequentialData() {
let data1 = await new Promise((resolve) => setTimeout(() => resolve('Data 1'), 2000));
console.log(data1);
let data2 = await new Promise((resolve) => setTimeout(() => resolve('Data 2'), 1000));
console.log(data2);
}
fetchSequentialData();
Combining Async/Await with Traditional Promises
You can combine async/await
with traditional Promise methods like then
and catch
.
Example:
async function fetchData() {
let data = await fetch('https://api.example.com/data');
return data.json();
}
fetchData().then((data) => {
console.log(data);
}).catch((error) => {
console.error(error);
});
Conclusion
Async/Await simplifies working with asynchronous operations in JavaScript by providing a cleaner and more readable way to write asynchronous code. It effectively replaces callbacks and makes working with Promises more intuitive.
Top comments (0)