Synchronous programming executes tasks one after another. Each task must finish before the next one begins, which can block execution.
console.log("Start");
// Simulating a delay using a loop
for (let i = 0; i < 1e9; i++) {}
console.log("End");
Explanation: The loop blocks the rest of the code. "End" is printed after the loop finishes.
Output:
Asynchronous programming allows tasks to be executed independently, preventing blocking.
console.log("Start");
setTimeout(() => {
console.log("This happens after 2 seconds");
}, 2000);
console.log("End");
Explanation: setTimeout does not block execution, so "End" is printed before the message inside the setTimeout callback.
Output:
Callback functions are passed as arguments to other functions and are executed when the task is finished.
console.log("Start");
function fetchData(callback) {
setTimeout(() => {
callback("Data fetched!");
}, 2000);
}
fetchData((message) => {
console.log(message); // This runs after 2 seconds
});
console.log("End");
Explanation: fetchData accepts a callback and executes it after the simulated delay.
Output:
Promises represent the eventual completion (or failure) of an asynchronous operation.
console.log("Start");
const myPromise = new Promise((resolve, reject) => {
const success = true; // Simulate success or failure
setTimeout(() => {
if (success) {
resolve("Promise resolved!");
} else {
reject("Promise rejected!");
}
}, 2000);
});
myPromise
.then((message) => {
console.log(message); // Runs when the promise is resolved
})
.catch((message) => {
console.log(message); // Runs if the promise is rejected
});
console.log("End");
Explanation: The promise resolves after 2 seconds, triggering the .then() method.
Output:
Multiple promises can be chained to handle sequential asynchronous tasks.
new Promise((resolve, reject) => {
setTimeout(() => resolve("Step 1 complete"), 1000);
})
.then((message) => {
console.log(message);
return new Promise((resolve) => setTimeout(() => resolve("Step 2 complete"), 1000));
})
.then((message) => {
console.log(message);
});
Explanation: Each promise resolves sequentially, logging "Step 1" and then "Step 2".
Output:
Promise.all() resolves when all promises in the array resolve.
const promise1 = new Promise((resolve) => setTimeout(() => resolve("First"), 1000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve("Second"), 2000));
Promise.all([promise1, promise2]).then((results) => {
console.log(results); // ["First", "Second"]
});
Explanation: Promise.all() waits for all promises to resolve and returns their results.
Output:
Promise.race() resolves when the first promise in the array resolves.
const promise1 = new Promise((resolve) => setTimeout(() => resolve("First"), 2000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve("Second"), 1000));
Promise.race([promise1, promise2]).then((result) => {
console.log(result); // "Second"
});
Explanation: Promise.race() resolves with the first promise that resolves.
Output:
Async/Await allows writing asynchronous code in a synchronous style.
console.log("Start");
async function fetchData() {
const promise = new Promise((resolve) => setTimeout(() => resolve("Data fetched!"), 2000));
const result = await promise; // Pauses here until promise is resolved
console.log(result);
}
fetchData();
console.log("End");
Explanation: The await pauses the execution until the promise resolves, so "End" is printed before "Data fetched!".
Output:
Fetch API is used to make HTTP requests asynchronously.
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json()) // Parse the JSON from the response
.then((data) => {
console.log(data); // Output the fetched data
})
.catch((error) => {
console.log("Error:", error); // Handle any errors
});
Explanation: Fetches data from a placeholder API and logs the response.
Output: