A Promise is a Javascript object that takes in a function, called the executor. The executor itself takes in two parameters, resolve
and reject
, that are themselves functions. Inside the promise, resolve
must be invoked with the sucessful returned value of the promise instance. You can also invoke the reject
function with the reason for the promise instance's failure, although doing so is optional.
Promises are used to capture the values of asynchronous functions. They resolve only once the asynchronous function has returned.
Promises have two very important methods: .then
and .catch
then
is used for chaining promises. You invoke .then
with one and optionally two functions. The first function specifies what to do in the case that the above promise fulfilled, and the second function specifies what to do in the case that the above promise rejected.
catch
is used for error handling. You invoke .catch
with a function which specifies what to do if any of the promises in the promise chain rejected.
const maybePuppy = () => {
let randomNum = Math.ceil( Math.random() * 10 ); // generate a random number between 1 and 10
if (randomNum % 2){ // if our random number is odd
return 'A PUPPY!'; // then we return a puppy
} else { // if it's even
return null; // we return nothing
}
};
const puppyPromise = new Promise( (resolve, reject) => { // here we are making a new promise instance
setTimeout( () => { // we are using setTimeout for 2 seconds to mimic an async request
let puppy = maybePuppy();
if (puppy) { // if our request returns a puppy, then we resolve with that puppy
resolve(puppy);
} else { // otherwise, if it returns null, we reject our promise with an error
reject(new Error( 'No puppies for you :(' ));
}
}, 2000);
});
puppyPromise
.then(puppy => console.log(puppy)) // if we get a puppy, we will log it here
.catch(console.error); // if we get an error, we will also log it
Try the above code block it out on repl.it!
Note that if we want to do anything with our returned puppy, we will have to do so WITHIN the promise chain, like so:
puppyPromise
.then(puppy => 'itty bitty ' + puppy.toLowerCase())
.then(modifiedPuppy => console.log(modifiedPuppy))
.catch(console.error);
Try the above code block out on repl.it!
The final promise method to be aware of is Promise.all
. Unlike .then
and .catch
, .all
is a method on the Promise constructor, not on its prototype. Promise.all
takes an array of promises, and returns a promise of an array.
const maybeBabyAnimal = (babyAnimal) => {
let randomNum = Math.ceil( Math.random() * 10 );
if (randomNum > 2){
return babyAnimal;
} else {
return null;
}
};
const puppyPromise = new Promise( (resolve, reject) => {
setTimeout( () => {
let puppy = maybeBabyAnimal('PUPPY');
if (puppy) {
resolve(puppy);
} else {
reject(new Error( 'Puppy promise rejected! No puppies for you :(' ));
}
}, 2000);
});
const kittyPromise = new Promise( (resolve, reject) => {
setTimeout( () => {
let kitty = maybeBabyAnimal('KITTY');
if (kitty) {
resolve(kitty);
} else {
reject(new Error( 'Kitty promise rejected! No kitties for you :(' ));
}
}, 2000);
});
const chickPromise = new Promise( (resolve, reject) => {
setTimeout( () => {
let chick = maybeBabyAnimal('CHICK');
if (chick) {
resolve(chick);
} else {
reject(new Error( 'Chick promise rejected! No chicks for you :(' ));
}
}, 2000);
});
Promise.all([puppyPromise, kittyPromise,chickPromise]) // Promise.all lets us pass an array of all our baby animal promises
.then(babyAnimals => babyAnimals.join(', '))
.then(babyAnimalStr => console.log(babyAnimalStr))
.catch(console.error); // if we get an error, print out the error so we know which promise rejected