Asynchronous Programming in Javascript
Here are some examples of asynchronous programming in JavaScript using callbacks, Promises, and async/await.
1. Using Callbacks
A callback is a function passed as an argument to another function, which is then executed after some operation completes. This approach was common in early JavaScript for handling asynchronous tasks, like data fetching.
Example: Fetching data with a callback
function fetchData(callback) {
setTimeout(() => {
const data = "Some fetched data";
callback(data);
}, 2000); // simulating network delay
}
fetchData((data) => {
console.log("Data received:", data);
});
In this example, fetchData
takes a callback function as an argument. After a delay, it calls the callback function with the fetched data.
2. Using Promises
Promises provide a cleaner way to handle asynchronous operations by avoiding "callback hell" (deeply nested callbacks). They have three states: pending, fulfilled, and rejected.
Example: Fetching data with a Promise
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = "Some fetched data";
resolve(data); // fulfill the promise
}, 2000);
});
}
fetchData()
.then((data) => {
console.log("Data received:", data);
})
.catch((error) => {
console.error("Error:", error);
});
In this example, fetchData
returns a Promise. We use .then()
to handle the data when the promise is fulfilled, and .catch()
to handle any errors if the promise is rejected.
3. Using async/await
async/await
syntax, introduced in ES8, makes asynchronous code look and behave more like synchronous code, improving readability. It works on top of Promises and allows you to "await" the completion of a promise within an async
function.
Example: Fetching data with async/await
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = "Some fetched data";
resolve(data);
}, 2000);
});
}
async function getData() {
try {
const data = await fetchData(); // wait for the promise to resolve
console.log("Data received:", data);
} catch (error) {
console.error("Error:", error);
}
}
getData();
In this example, the getData
function is marked as async
, allowing us to use await
to pause the function until fetchData
resolves. This results in a more readable and manageable way to handle asynchronous code.
4. Real-World Example: Fetching Data from an API
Here’s how you might fetch data from an API using fetch
with async/await:
async function fetchFromAPI() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log("Data from API:", data);
} catch (error) {
console.error("Fetch error:", error);
}
}
fetchFromAPI();
In this example:
We use
await fetch(url)
to wait for the API call to complete.We check if the response is okay (
response.ok
). If not, we throw an error.If successful, we parse the response data with
.json()
and log it to the console.
Subscribe to my newsletter
Read articles from David Gostin directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
David Gostin
David Gostin
Full-Stack Web Developer with over 25 years of professional experience. I have experience in database development using Oracle, MySQL, and PostgreSQL. I have extensive experience with API and SQL development using PHP and associated frameworks. I am skilled with git/github and CI/CD. I have a good understanding of performance optimization from the server and OS level up to the application and database level. I am skilled with Linux setup, configuration, networking and command line scripting. My frontend experience includes: HTML, CSS, Sass, JavaScript, jQuery, React, Bootstrap and Tailwind CSS. I also have experience with Amazon EC2, RDS and S3.