JavaScript, being single-threaded, executes code sequentially. This means that if there’s a long-running operation (like fetching data from a server), the entire application can feel locked up while waiting. To handle such scenarios, JavaScript introduced asynchronous programming, which allows you to execute code concurrently. Two powerful tools in this domain are Promises and async/await.
A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It can be in one of three states:
Here’s how you can create a simple Promise:
let myPromise = new Promise((resolve, reject) => { const success = true; // Change this to false to see the rejection if (success) { resolve("Operation was successful!"); } else { reject("Operation failed!"); } });
You can handle the result of a Promise using the .then()
and .catch()
methods:
myPromise .then(result => { console.log(result); // Output: Operation was successful! }) .catch(error => { console.error(error); });
Promises help in dealing with asynchronous operations more effectively than using traditional callback functions. They make the code more readable and easier to manage, especially when handling multiple asynchronous tasks.
You can chain multiple Promises together:
let fetchData = new Promise((resolve) => { setTimeout(() => { resolve("Fetched data after 2 seconds"); }, 2000); }); fetchData .then(data => { console.log(data); return "Processing data..."; }) .then(processed => { console.log(processed); });
While Promises improve the handling of asynchronous code, the async/await syntax takes it a step further, allowing you to write asynchronous code that looks synchronous.
The async
keyword is used to define an asynchronous function. Within this function, you can use the await
keyword.
await
is used in conjunction with a Promise and tells the code to wait until the Promise settles (either fulfilled or rejected) before moving on.
Let's rewrite our previous example using async/await:
const fetchData = () => { return new Promise((resolve) => { setTimeout(() => { resolve("Fetched data after 2 seconds"); }, 2000); }); }; const processAsyncData = async () => { try { const data = await fetchData(); console.log(data); // Output: Fetched data after 2 seconds console.log("Processing data..."); } catch (error) { console.error("Error fetching data:", error); } }; processAsyncData();
Handling errors with async/await is straightforward with try/catch blocks, making your code cleaner:
const fetchDataWithError = () => { return new Promise((resolve, reject) => { const success = false; // Change this to true to simulate success if (success) { resolve("Data received!"); } else { reject("Error fetching data!"); } }); }; const run = async () => { try { const result = await fetchDataWithError(); console.log(result); } catch (error) { console.error(error); // Output: Error fetching data! } }; run();
Imagine you’re working on a web application where you need to fetch user data from an API and also fetch their posts. You can accomplish this elegantly with async/await:
const fetchUserData = async (userId) => { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`); return await response.json(); }; const fetchUserPosts = async (userId) => { const response = await fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`); return await response.json(); }; const getUserInfo = async (userId) => { try { const user = await fetchUserData(userId); const posts = await fetchUserPosts(userId); console.log(user); console.log(posts); } catch (error) { console.error("Error:", error); } }; getUserInfo(1);
With async/await, your chaining of asynchronous operations becomes straightforward, improving both readability and maintainability.
The combination of Promises and async/await provides a robust way to handle asynchronous operations in JavaScript, allowing for cleaner, more readable code. By utilizing these features, developers can greatly enhance their JavaScript applications, leading to better performance and user experience. As you continue to build applications, keep in mind how these tools can simplify your code and make your asynchronous tasks more manageable.
14/09/2024 | VanillaJS
22/10/2024 | VanillaJS
15/10/2024 | VanillaJS
14/09/2024 | VanillaJS
14/09/2024 | VanillaJS
22/10/2024 | VanillaJS
22/10/2024 | VanillaJS
22/10/2024 | VanillaJS
22/10/2024 | VanillaJS
22/10/2024 | VanillaJS