What are Promises ?
promises are objects that represent the eventual completion or failure of an async task!!.
(Assume the Promise is just as "Promise" from plain English language.).
"😎 JavaScript promises are more reliable than the promises that your partner made"
When you create a promise, it will be in one of the following states:
- Pending: The initial state of the Promise before it is fulfilled or rejected.
- Fulfilled: The state of the Promise representing a successful operation.
- Rejected: The state of the Promise representing a failed operation
If your partner promises you that "we will be together"💕 consider this as a Pending promise🤞, However he/she dumps💩 you then consider it as Rejected promise😭. But if he/she was a green flag and finally you both get married💑 then it is a Fulfilled promise😎.
You can create new promise using the Promise
constructor, and you can attach callbacks to it using the .then()
and .catch()
methods to handle the resolved value or the error, respectively.
Here is a syntax to create a promise!! . Try running this code itself
const promise = new Promise((resolve,reject)=>{
//console.log("Try to run me before writing last line see what happens!!")
resolve("Success!!!")
})
promise.then(data=>console.log(data))
Also, Let me know that if we uncomment the second line, and simply run the code after declaring promise,
Another example with a rejected promise!!!
const promise = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject("Failure!!!")
},3000)
})
promise.then(data=>console.log(data)).catch(err=>console.error(err))
TASK : Can you write a relationship promise ? prompt a question "Do you want to marry me ?" If the user inputs "Yes" then the promise must be fulfilled after- 3 sec. and if user inputs "No" then the promise should rejects! (Challenge :- Try to make it with the DOM Manipulation A Input and Button Ask and reply should be below!!, You can also get creative if you want.)
Advance Concepts of Promises.
There are also some Techniques to optimize the performance. You can try them below
Here's a breakdown of the differences between Promise.all
, Promise.allSettled
, and Promise.race
:
1.Promise.all:
- It takes an iterable of promises as an input.
- Resolves when all the promises in the iterable have resolved.
- If any promise rejects, the entire
Promise.all
call is rejected immediately with the reason of the first rejected promise. - Returns an array of the resolved values in the same order as the input promises.
2.Promise.allSettled:
- It takes an iterable of promises as an input.
- Resolves when all the promises in the iterable have either resolved or rejected.
- It does not short-circuit when a promise rejects, and it waits for all the promises to settle before resolving.
- Returns an array of objects representing the outcome of each promise, including a `status` property indicating whether the promise was fulfilled or rejected, along with a `value` or `reason` property.
3.Promise.race:
- It takes an iterable of promises as an input.
- Resolves or rejects as soon as one of the promises in the iterable resolves or rejects.
- Returns the value or reason from the first settled promise.
- It does not wait for all promises to settle and can be used to implement a timeout feature or race conditions between different asynchronous operations.
These methods provide different ways of handling multiple promises, allowing you to manage asynchronous operations effectively depending on your specific use case.
Promise.all
Another Example
let job = (delay)=>{
return new Promise((resolve)=>{
setTimeout(()=>{
console.log("message : "+ delay)
resolve(delay)
}, delay)
})
}
Promise.all([job(5000), job(2000), job(3000)]).then(data=>{ console.log("printing : \n"); data.forEach(item=>console.log(item))}).catch(err=>console.log(err))
//Output :
//message : 2000
//message : 3000
//message : 5000
//printing :
//5000
//2000
//3000
*Promise.all
fails if any one of the promise fails Example : *
let p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'p1');
});
let p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000, 'p2');
});
let p3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1200, 'p3');
});
let p4 = new Promise(function(resolve, reject) {
setTimeout(reject, 300, 'p4');
});
let p5 = new Promise(function(resolve, reject) {
setTimeout(resolve, 800, 'p5');
});
let p6 = new Promise((resolve, reject)=>{
resolve('P6')
})
let promise = Promise.all([p1, p2, p3, p4, p5, p6]);
promise
.then(function(data) {
data.forEach(function(data) {
console.log(data);
});
})
.catch(function(error) {
console.error('error', error);
});
//Output
//Error: error p4
Now there is one thing can be done in order to avoid short circuiting is. To use promise.allSettled
but Then it will log the settled promises as an object.
or Alternatively all promise.all
with each catch calls like following
let promise = Promise.all([p1.catch(()=>{}), p2.catch(()=>{}), p3.catch(()=>{}), p4.catch(()=>{}), p5.catch(()=>{}), p6.catch(()=>{})]);
//output
//p1
//p2
//p3
//undefined
//p5
//P6
In the same above example let us use the promise.race
let promise = Promise.race([p1, p2, p3, p4, p5, p6]);
promise
.then(function(data) {
console.log(data);
})
.catch(function(error) {
console.error('error', error);
});
//Output
P6
Promise Chaining
consider the following code
var promise = job1();
promise
.then(function(data1) {
console.log('data1', data1);
return job2();
})
.then(function(data2) {
console.log('data2', data2);
return 'Hello world';
})
.then(function(data3) {
console.log('data3', data3);
}).then(data=>console.log(data));
function job1() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('result of job 1');
}, 1000);
});
}
function job2() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('result of job 2');
}, 1000);
});
}
///Output
//data1 result of job 1
//data2 result of job 2
//data3 Hello world
//undefined
- We call
job1
and we store the returned promise in a variable calledpromise
. - We call
then
on this promise and we attach a callback for when the promise is resolved - We print
data1
and it is obvioulsyresult of job 1
- we call
job2
and we return the resulting promise. - We call
then
on the result of the firstthen
. The result ofthen
is always a promise. Always. At worst, it can be a never resolved promise, but it is a promise. In this case, the promise is the return value ofjob2
. When you are in athen
callback, if you return a promise, it will be the resulting promise of thethen
call. - We print
data2
. According to theresolve
call in the promise returned byjob2
,data2
isresult of job 2
. By chaining our 2 promises (job1
thenjob2
),job2
is always executed afterjob1
. - We return a simple string
'Hello world'
. - We call
then
on the result of thethen
call . The promise here is an auto-resolved promise, and it will pass'Hello world'
in the data. When you are in athen
callback, if you return anything but a promise, an auto-resolved promise is created, and this promise will be the result of thethen
call. - We print
data3
and this is the'Hello world'
will return.
The Broken Chain !
function test() {
var promise = job();
promise.then(function(data) {
doSomething(data);
});
return promise;
}
In this code the promise.then
is not returned, in-fact the function test returns the initial promise. and therefore the result of the promise.then
is lost. Because there is no one can interact with it.
How to fix it?
function test() {
return job().then(function(data) {
doSomething(data);
});
}
Creating auto Resolve and auto Reject promises
function job() {
if (test) {
return aNewPromise();
} else {
return Promise.resolve(42); // return an anto-resolved promise with `42` in data.
}
}
Promise.resolve(42)
Auto-resolve promise
promise.reject('error')
Auto reject promise
As a rule of thumb 👍: whenever a function can return a promise, ALWAYS return a promise.
success defeat error Error caught
Test Example to test Chaining with Catch
function job(state) {
return new Promise(function(resolve, reject) {
if (state) {
resolve('success');
} else {
reject('error');
}
});
}
let promise = job(true);
promise
.then(function(data) {
console.log(data);
return job(true);
})
.then(function(data) {
if (data !== 'victory') {
throw 'Defeat';
}
return job(true);
})
.then(function(data) {
console.log(data);
})
.catch(function(error) {
console.log(error);
return job(false);
})
.then(function(data) {
console.log(data);
return job(true);
})
.catch(function(error) {
console.log(error);
return 'Error caught';
})
.then(function(data) {
console.log(data);
return new Error('test');
})
.then(function(data) {
console.log('Success:', data.message);
})
.catch(function(data) {
console.log('Error:', data.message);
});
//Output:
//success, Defeat, error, Error caught, Success: test
So as per my understanding based on the example above. Promise is resolve it goes to the success callback function chained with .then function(). But if promise is rejected and the error is thrown by means of throw new Error or throw Error, Then it is caught by the catch block.
Now if the catch block returns anything, then the chaining continues with the .then callback function but if catch block throws error then it will be caught by the next catch block.
Also if the promise is rejected then the catch block is executed with the error message.
Top comments (1)
I appreciate the description detail and humor in your article!
I often see Promises with unnecessary wrapper functions, like
.then(data=>console.log(data)
instead of.then(console.log)
. While there are cases where wrappers can be necessary, it can be much easier to read when we directly pass named functions.It's the first of the tips in a post I made last year, if you are interested.