Asynchronous call
Imagine a new ATM 💰 is installed in a shopping center. There were initially 10 to 15 users. The machine can only serve one person at a time, which at first seems insignificant to the user, but as the number of users rises, the difficulty will also rise. The execution is synchronous. It is similar to a compiler running each piece of code one at a time.
PROBLEM:
Everything will function normally for the first few days because there won't be many clients. However, when the number of clients grows, the issue will become apparent.
As every problem has a solution this too has the same!!
SOLUTION:
One nice day👏, a different bank 💳 got permission to go to the same marketplace and install a new ATM close to the old one. This seems like the asynchronous process in many ways. The queue at ATM 1 will be shorter because the consumer will be directed to the second ATM. A blocking 🚫 process is another name for the synchronous process discussed above. This prevents other procedures from moving forward. That's why running file uploading processes should be asynchronous.
JavaScript's asynchronous nature allows you to perform tasks without blocking 🚫the main program flow, leading to more efficient use of resources and improved user experiences, especially in scenarios involving network requests, I/O operations, and other time-consuming tasks.
In JavaScript we can do this in 3 ways-
- Callback function
- Promises
- async-await
In this blog we'll focus on promises
Promises
A Promise 🤝in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Promises provide a structured way to handle asynchronous code, making it more readable and manageable compared to traditional callback-based approaches.
In JavaScript, asynchronous functions, including those declared using the async keyword, always return a Promise. This is a fundamental characteristic of how asynchronous operations are handled in the language.
Promises have three states:
1.Pending: The initial state. When we create a promise by-default
it is pending because we haven't called resolve or reject yet.
That is promise is neither fulfilled nor rejected; it's in
progress.
2.Fulfilled: The asynchronous operation completed successfully,
and the promise is resolved. The promise's value is available.
3.Rejected: The asynchronous operation encountered an error, and
the promise is rejected. The reason for rejection (an error
object) is available.
Structure of promise has 2 parts :-
One who makes the promise
//promise maker
Another one who receives the promise
//promise receiver
//PROMISE MAKER
const myPromise = new Promise((resolve, reject) => {
// Asynchronous operation here
if (/* operation successful */) {
resolve(result); // Fulfill the promise
} else {
reject(error); // Reject the promise
}
});
//PROMISE RECEIVER
myPromise
.then(result => {
// Handle the fulfilled promise
})
.catch(error => {
// Handle the rejected promise
});
The resolve
function is the success function and should be called whenever the promise was successful.
The reject
function is the error function and should be called whenever the promise was not able to be completed successfully.
The best way to think of promises is to just think of resolve
as the same as .then
and reject
as the same as .catch
.
ERROR HANDLING OF PROMISE
In Promises, error handling is done using the .catch()
method.
The .catch()
method is used to handle any errors that occur during the promise chain. When an error occurs in any part of the promise chain, it will immediately jump to the nearest .catch()
block.
Please note: throw error
is to throw error intentionally.
.catch()
is used to catch any error that has occurred.
Real use case example:
We'll use the Fetch API to make an asynchronous HTTP request and retrieve data from a JSON placeholder API.
function fetchDataWithPromise() {
return fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => {
return data;
})
.catch(error => {
console.error('Error fetching data:', error);
//throw error;
});
}
// Calling the function and handling the data using Promises
fetchDataWithPromise()
.then(posts => {
//console.log(`Posts fetched using Promises:, ${posts}`);
posts.map((post)=>{
console.log(`Title : ${post.title}`);
})
})
.catch(error => {
console.error('Error handling data:', error);
throw error;
});
CHAINING OF PROMISE
You can chain as many functions as you want and you can see the information will flow from one to the to the next now it may not seem obvious but there are major readability benefits to what we have here. It can be chained to handle multiple asynchronous operations sequentially.
Ps: Do read comments of the code below to get better understanding!
//CREATER
function getWeather(){
return new Promise(function(resolve,reject){
setTimeout(() => {
resolve('cloudy');
//reject('bunny');
}, 100);
})
}
function getWeatherIcon(weather){
return new Promise(function(resolve,reject){
setTimeout(()=>{
switch(weather){
Case 'sunny':
resolve('🌞')
break;
case 'cloudy':
resolve('☁️')
break;
case 'rainy':
resolve('🌧️')
break;
default:
reject('I cant find');
}
},1000)
})
}
//MAKER
function onSuccess(data){
//console.log(`success : ${data}`);
//To get output on screen/client side we'll Create a new div element
const resultDiv = document.createElement("div");
// Set the content of the div to the success message and data
resultDiv.textContent = `Success: ${data}`;
// Append the div element to the body or another parent element
document.body.appendChild(resultDiv);
}
function onError(error){
console.log(`Error : ${error}`);
}
//this is how two funcitons (here getWeather & getWeatherIcon) are chained together
getWeather()
.then(getWeatherIcon) //<--- here getWeatherIcon we don't need to pass arguments as whatever we get from getWeather automatically gets chained & passes in the information further to .then ()...
.then(onSuccess,onError);//1 parameter is called when promise resolves successfully & 2 parameter called when its rejected;
Click hereto run the code & see output.
So summing up promises what we understood is : Asynchronous function takes unknown amount of time so its necessary to return something immediately(Instead every function needs to return something else it will return undefined)
So instead of returning some data which we don't have it returns a promise of some data => it's like a train ticket meaning after getting it doesn't mean immediately you will ride the train but instead a ticket is kind of promise 🤝 that on a certain date you will ride the train.
Promise object takes a function where we add async logic (eg-making call to backend, waiting for some function like setTimeout)
Pseudo code:
function fun1(){
return new Promise((resolve,reject)=>{
resolve('Hello')
})
}
function fun2(data){
return new Promise((resolve,reject)=>{
resolve(data);
})
}
function fun3(data){
return new Promise((resolve,reject)=>{
resolve(data);
})
}
fun1()
.then(fun2)
.then(fun3)
.catch(error=>{
console.log(error)
})
.finally(()=>{
console.log("Finally is called every time whether it's resolve or re
The finally() method is always executed whether the promise is fulfilled or rejected.
Hope you get all the concepts very well👐
If you are reading till here 😇, do not forget to hit like💗
Do comment and let me know how did you like the blog.
If struck feel free to reach out to me and post you doubt in comment section, I'll try my best to answer them.
Follow me for more such fundamental driven concepts 👍
Top comments (0)