Introduction
In JavaScript, asynchronous and synchronous calls refer to different ways of executing code and handling operations. Understanding these concepts is crucial for developing efficient and responsive JavaScript applications.
Synchronous Calls in JS
Synchronous calls, also known as blocking calls, execute one operation at a time, waiting for each operation to complete before moving on to the next. When a synchronous call is made, the program waits for that operation to complete before moving on to the next line of code. This means that the execution of code is halted until the current operation is finished. Synchronous calls can be useful when you need to ensure that certain operations are completed in a specific order.
Example of Synchronous calls
function abc(){
console.log("we are inside function");
}
console.log("start");
abc();
console.log("end");
Output:
Asynchronous Calls
Asynchronous calls, also known as non-blocking calls, allow the program to continue executing other operations without waiting for the current operation to finish. Asynchronous operations are typically used for tasks that may take some time, such as fetching data from a server, reading a file, or waiting for user input. Instead of blocking the execution, asynchronous calls initiate the operation and provide a callback function to handle the result once it becomes available.
Example of Asynchronous calls
console.log("Start");
setTimeout(() => {
console.log("we are in settimeout");
})
console.log("End");
Output:
Where Asynchronous JS is used ?
console.log("start");
function login(email, pass) {
setTimeout(() => {
console.log("now we have data");
return { rating: 3 };
}, 3000);
}
const userRating = login("abc@gmail.com", 1234567890);
console.log(userRating);
console.log("end");
In the given scenario, the client needs to retrieve data from the server using the login function. However, due to the uncertainty of the server's response time, a setTimeout function is employed to introduce a delay of 3 seconds. Consequently, the login function is called to fetch the data and store it in the variable userRating. Nevertheless, when attempting to log userRating to the console, it displays as undefined. This unexpected outcome can be attributed to the asynchronous nature of the setTimeout function, which pushes the subsequent statement to the Web APIs queue and allows it to proceed. As a result, the console.log statement is executed before the server response is received, leading to the undefined value of userRating.
To overcome this problem callback function is used
console.log("start");
function login(email, pass, callback) {
setTimeout(() => {
console.log("now we have data");
callback({ rating: 3 });
}, 3000);
}
const userRating = login("abc@gmail.com", 1234567890, (user) => {
console.log(user);
});
console.log(userRating);
console.log("end");
Understanding the Event Loop
The event loop is a fundamental concept in JavaScript that enables asynchronous behavior. It continuously checks the call stack and task queue, ensuring that the tasks are executed in the correct order. The event loop allows JavaScript to perform non-blocking operations, improving the overall performance of applications.
Callbacks
Callbacks are a traditional approach to handling asynchronous operations in JavaScript. A callback is a function that gets executed after a certain task is completed. Here's how to use callback functions:
function fetchData(callback) {
// Simulating an asynchronous operation
setTimeout(function () {
const data = "Some data";
callback(data);
}, 2000);
console.log("Data received");
//but in actual, data is not received
//it will be received after 2 seconds
}
function processData(data) {
console.log("Data:", data);
}
fetchData(processData);
Output:
Promises
Promises provide a more structured and flexible way of handling asynchronous operations. A promise represents the eventual completion or failure of an asynchronous task. Here's an example of using promises:
function fetchData() {
return new Promise(function(resolve, reject) {
// Simulating an asynchronous operation
setTimeout(function() {
const data = 'Some data';
resolve(data);
}, 2000);
console.log("Data received");
});
}
fetchData()
.then(function(data) {
console.log('Data:', data);
})
.catch(function(error) {
console.error('Error:', error);
});
Output:
Async/Await
Async/await is a modern approach introduced in ECMAScript 2017 for writing synchronous-like code that handles asynchronous operations. It provides a more readable and concise syntax. Here's an example:
async function fetchData() {
return new Promise(function(resolve, reject) {
// Simulating an asynchronous operation
setTimeout(function() {
const data = 'Some data';
resolve(data);
}, 2000);
});
}
async function processData() {
try {
const data = await fetchData();
console.log('Data:', data);
} catch (error) {
console.error('Error:', error);
}
}
processData();
Output:
Synchronous Implementation with Async/Await:
function fetchData() {
return new Promise(function(resolve, reject) {
// Fetch data from an API asynchronously
fetch('https://gorest.co.in/public/v2/users')
.then(function(response) {
resolve(response.json());
})
.catch(function(error) {
reject(error);
});
});
}
fetchData()
.then(function(data) {
// Display the data
console.log(data);
})
.catch(function(error) {
console.error('Error:', error);
});
Output:
Youtube Video
Conclusion
Asynchronous and synchronous calls play a vital role in JavaScript programming. By understanding and effectively utilizing techniques like callback functions, promises, and async/await, developers can handle asynchronous operations efficiently. Additionally, comprehending the event loop and writing non-blocking code enhances the performance and responsiveness of JavaScript applications. Mastering these concepts empowers developers to create robust and user-friendly web experiences.