The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
-
Pending: initial state, neither fulfilled nor rejected.
-
Fulfilled: meaning that the operation completed successfully.
-
Rejected: meaning that the operation failed.
A Promise object is created using the new
keyword with its constructor, this constructor will accept one function argument called "Executer function".
The Executer function will accept two functions as parameters:
-
resolve: called when asynchronous task completes successfully and returns the results of the task as a value.
-
reject : called when the task fails, and returns the reason for failure, which is typically an error object.
We will follow the same examples used in callback, and see how they will work with promise, this is Example 9.1 but using promise
var x = 1;
function asyncIncrement(){
return new Promise(function(resolve , reject){
try{
setTimeout(function(){ //to be able to reach reject change setTimeout to setTTimeour to result in an error and end inside catch and finally call reject
x++;
resolve(x);
},1000);
}
catch(error){
reject(error);
}
});
}
asyncIncrement()
.then(function(incrementedValue){
console.log(incrementedValue);
})
.catch(function(error){
console.log(error);
});
Promise chaining is to return new promise in resolve function of previous promise, it's very helpful in situation where multiple async operations needs to be executed sequentially
Now we see how promise chain, fix callback hell that result from nested async operations, this example is a copy from Example 9.4 but instead of using nested callback functions we will use promise chaining
var x = 1;
function asyncIncrementOne(){
return new Promise(function(resolve , reject){
try{
setTimeout(function(){
x+=1;
resolve(x);
},1000);
}
catch(error){
reject(error);
}
});
}
function asyncIncrementTwo(){
return new Promise(function(resolve , reject){
try{
setTimeout(function(){
x+=2;
resolve(x);
},1000);
}
catch(error){
reject(error);
}
});
}
function asyncIncrementThree(){
return new Promise(function(resolve , reject){
try{
setTimeout(function(){
x+=3;
resolve(x);
},1000);
}
catch(error){
reject(error);
}
});
}
incrementValueOne()
.then(function(asyncIncrementOne){
console.log(asyncIncrementOne);
return asyncIncrementTwo();
})
.then(function(asyncIncrementTwo){
console.log(asyncIncrementTwo);
return asyncIncrementThree();
})
.then(function(asyncIncrementThree){
console.log(asyncIncrementThree);
})
.catch(function(error){
console.log(error);
});
//result
//2
//4
//7
Sometimes we encouter a situation where we need to get a final value or execute specific function after a set of non related async operations are all done, this is when Promise.all
will be useful.
Promise.all
will accept an array of Promise objects, and when all of them are fulfilled it will fire one then
containing the array of results.
We will get the result of our three async functions inside one .then
function.
var x = 1;
function asyncIncrementOne(){
return new Promise(function(resolve , reject){
try{
setTimeout(function(){
x+=1;
resolve(x);
},1000);
}
catch(error){
reject(error);
}
});
}
function asyncIncrementTwo(){
return new Promise(function(resolve , reject){
try{
setTimeout(function(){
x+=2;
resolve(x);
},1000);
}
catch(error){
reject(error);
}
});
}
function asyncIncrementThree(){
return new Promise(function(resolve , reject){
try{
setTimeout(function(){
x+=3;
resolve(x);
},1000);
}
catch(error){
reject(error);
}
});
}
Promise.all([asyncIncrementOne() , asyncIncrementTwo() , asyncIncrementThree()])
.then(function(results){
console.log(results[0]);
console.log(results[1]);
console.log(results[2]);
})
.catch(function(error){
console.log(error);
});
//result
//2
//4
//7