Everything You Need to Know About Async JavaScript
Sync and Async In JS:
Sync (Synchronous):
In synchronous JavaScript, code executes line by line in sequence.
Each operation waits for the previous one to finish before executing.
This means:
- Tasks are dependent on execution order
- One task can block the next task
console.log("Line 1");
console.log("Line 2");
console.log("Line 3");
/*
Output:
Line 1
Line 2
lIne 3
*/Asyn (Asynchronous):
In asynchronous JavaScript, some operations take time to complete, such as:
- API calls
- Timers
- File operations
These operations do not block the main thread.
JavaScript continues executing the remaining code while the async task runs in the background.
This means:
- Later synchronous code may execute before async code finishes
- The main thread remains non-blocking
console.log("Start");
setTimeout(() => {
console.log("Async Operation");
}, 2000);
console.log("End"); // this line will execute before setTimeout
/*
Start
End
Async Operation
*/How do we convert sync code to async code?
We can convert ‘Synchronous’ code into ‘Asynchronous’ code by moving our code inside time-consuming operations
JavaScript provides asynchronous APIs such as:
setTimeout()setInterval()fetch()- Promises
- async/await
- File system APIs (Node.js)
Synchronous Code
console.log('Start');
console.log('Make Me Async');
conole.log('End');
/*
Here, the code executes line by line synchronously.
Output:
Start
Make Me Async
End
*/
Converting Sync to Async Using setTimeout
console.log('Start');
setTimeout(() => {
console.log('Make Me Async'); // will be printed after 1 second
}, 1000)
conole.log('End');
/*
Now "Make Me Async" is scheduled asynchronously using setTimeout().
Output:
Start
End
Make Me Async
*/Callback & Callback Hell
Callback:
A callback is a function that is passed as an argument to another function and is executed later when a specific task is completed.
function calculator(num1, num2, callback) {
return callback(num1, num2);
}
function addTwoNumbers(num1, num2) {
return num1 + num2;
}
const result = calculator(2, 3, addTwoNumbers);
console.log(result); // Output: 5What is Callback Hell?
Callback Hell is a situation where deeply nested callbacks make asynchronous code hard to read and manage, causing the code to grow horizontally like a pyramid.
loginUser(user, () => {
getProfile(() => {
getPosts(() => {
getComments(() => {
console.log("Done");
});
});
});
});Problems with Callback Hell
- Poor readability
- Difficult debugging
- Hard maintenance
- Complex error handling
Solution
Callback Hell can be solved using:
- Promises with
.then() async/await
// Using Promises
loginUser(user)
.then(getProfile)
.then(getPosts)
.then(getComments)
.then(() => {
console.log("Done");
})
.catch((err) => {
console.log(err);
});
// Using async/await
async function handleUser() {
try {
const profile = await loginUser(user);
const posts = await getPosts(profile);
const comments = await getComments(posts);
console.log("Done");
} catch (err) {
console.log(err);
}
} Web Browser API’s
Web APIs are features provided by the browser that allow JavaScript to perform operations that the JavaScript engine itself cannot do.
- create timers
- make HTTP requests
- access the DOM
- handle user events
These capabilities are provided by the browser through Web APIs.
Common Web APIs
setTimeout()setInterval()fetch()- DOM APIs
- Geolocation API
- Local Storage API
- WebSocket API
Code Examples
// setTimeout()
setTimeout(() => {
console.log("Timer Completed");
}, 2000)
// setInterval()
let count = 1;
setInterval(() => {
console.log(count);
count++;
}, 1000);
// fetch()
fetch("https://dummy.api/data")
.then((response) => response.json())
.then((data) => {
console.log(data);
});
// DOM API
const button = document.getElementById("btn");
button.addEventListener("click", () => {
console.log("Button Clicked!");
});
Promise
What is Promise?
A Promise is a JavaScript object that represents the eventual completion or failure of an asynchronous operation and its resulting value.
Promise States
pending:initial statefulfilled:operation completed successfullyrejected:operation failed
const promise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("Task completed");
} else {
reject("Task failed");
}
});Common Promise Methods
.then() Handles successful result
.catch()Handles errors
.finally()Runs regardless of success/failure
Promise.resolve()Creates resolved promise
Promise.reject()Creates rejected promise
Promise.all()Waits for all promises
Promise.race()Returns first settled promise
Promise.allSettled()Waits for all promises regardless of result
Get Kumarpawanm’s stories in your inbox
Join Medium for free to get updates from this writer.
Promise.any()Returns first fulfilled promise
.then()
const promise = Promise.resolve("Success");
promise.then((data) => {
console.log(data);
});.catch()
const promise = Promise.reject("Something went wrong");
promise.catch((err) => {
console.log(err);
});.finally()
Promise.resolve("Done")
.finally(() => {
console.log("Cleanup completed");
});Promise.resolve()
Promise.resolve(100)
.then((data) => {
console.log(data);
});Promise.reject()
Promise.reject("Error occurred")
.catch((err) => {
console.log(err);
});Promise.all()
const p1 = Promise.resolve("A");
const p2 = Promise.resolve("B");
Promise.all([p1, p2])
.then((data) => {
console.log(data);
});Promise.race()
const p1 = new Promise((resolve) => {
setTimeout(() => resolve("First"), 1000);
});
const p2 = new Promise((resolve) => {
setTimeout(() => resolve("Second"), 2000);
});
Promise.race([p1, p2])
.then((data) => {
console.log(data);
});Promise.allSettled()
const p1 = Promise.resolve("Success");
const p2 = Promise.reject("Failed");
Promise.allSettled([p1, p2])
.then((data) => {
console.log(data);
});Promise.any()
const p1 = Promise.reject("Error");
const p2 = Promise.resolve("Success");
Promise.any([p1, p2])
.then((data) => {
console.log(data);
});Inversion of control
Inversion of Control means transferring the control of execution from your code to another system, function, or framework.
In JavaScript, Inversion of Control commonly happens with callbacks.
setTimeout(() => {
console.log("Hello");
}, 1000);
/*
you are giving control of your callback to: setTimeout
you do not control when callback executes
browser controls execution timing
*/Why IoC Can Become Problematic
- callback may execute multiple times
- callback may never execute
- error handling becomes difficult
- hard to trust external code
function fetchData(callback) {
setTimeout(() => {
callback("Data received");
}, 2000);
}
fetchData((data) => {
console.log(data);
});
/*
Here:
fetchData controls when callback runs
your callback execution depends on another function
*/How Promises Solve This
fetchData()
.then((data) => {
console.log(data);
});Promises guarantee:
- callback runs once
- value cannot change unexpectedly
- better error handling
Event Loop in JS
The Event Loop is a mechanism in JavaScript that continuously monitors the Call Stack and task queues to manage asynchronous operations.
Why Do We Need the Event Loop?
JavaScript executes only one task at a time because it has:
- one Call Stack
- one main thread
But JavaScript also supports:
- timers
- API calls
- DOM events
- promises
The Event Loop coordinates the execution of asynchronous tasks by moving them from task queues to the Call Stack.
Main Components
callstack: Executes synchronous code
Web APIs: Handle async operations
Callback Queue: Stores macrotasks
Microtask Queue: Stores promise callbacks
Code Example
console.log("Start");
setTimeout(() => {
console.log("Timer");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("End");
/*
Output:
Start
End
Promise
Timer
*/
/*
*Step-by-Step Execution*
1. console.log("Start")
Runs immediately.
Output: Start
2. setTimeout()
Timer registered in Web APIs
Callback waits in Callback Queue later
3. Promise.then()
Promise callback goes into: Microtask Queue
4. console.log("End")
Runs immediately.
Output: End
5. Call Stack Becomes Empty
Now Event Loop starts checking queues.
Priority Order:
Microtask Queue
↓
Callback Queue
6. Promise Callback Executes
Output: Promise
7. setTimeout Callback Executes
Output: Timer
*/
Fetch API
What is Fetch API?
fetch() is a Web API used to make HTTP requests in JavaScript.
It returns a Promise.
fetch(url, options)
/*
url → API endpoint
options → request configuration
*/Common HTTP Methods
GETRetrieve data
POSTCreate data
PUTUpdate the entire resource
PATCHUpdate partial resource
DELETEDelete resource
Code Examples
GET Request
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((res) => res.json())
.then((data) => {
console.log(data);
});POST Request
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
title: "JavaScript",
body: "Learning fetch API"
})
})
.then((res) => res.json())
.then((data) => {
console.log(data);
});PUT Request
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
id: 1,
title: "Updated Title",
body: "Updated Body"
})
})
.then((res) => res.json())
.then((data) => {
console.log(data);
});DELETE Request
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "DELETE"
})
.then((res) => {
console.log("Deleted Successfully");
});Error Handling in Async Code
Error Handling with Callbacks
function findUserByUserName(userName, callback){
setTimeout(() => {
if (userName) {
callback(null, "User Data");
} else {
callback(new Error("Invalid user name!"), null);
}
}, 1000);
}
findUserByUserName('user@gmail.com', (err, data) => {
if (err) {
console.log(err.message);
return;
}
console.log(data);
})Error Handling with Promises
const promise = new Promise((resolve, reject) => {
const success = false;
if (success) {
resolve("Task Completed");
} else {
reject(new Error("Task Failed"));
}
});
promise
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err.message);
});Error Handling with async/await
async function getData() {
try {
const response = await fetch("https://invalid-url.com");
const data = await response.json();
console.log(data);
} catch (err) {
console.log("Error:", err.message);
}
}
getData();Error Handling inside setTimeout
setTimeout(function() {
try {
var result = JSON.parse("invalid json");
console.log(result);
} catch (error) {
console.error("Parsing failed:", error.message);
}
}, 1000);


