10 Things I Learned About Promises
Promise chaining only works if your fulfillment handlers actually return promises. Three patterns where that's easy to get wrong, and what happens when you don't.
A list of things that I've learned while using promises...
Promises that immediately resolve
var p = new Promise(function(resolve, reject){
resolve(42);
});You can do:
var p = Promise.resolve(42);Returning Promises
The following does not print out statements one second apart:Promise.resolve(42).then(function(){
window.setTimeout(function(){
console.log(window.performance.now());
}, 1000);
}).then(function(){
window.setTimeout(function(){
console.log(window.performance.now());
}, 1000);
});The fulfillment handler for the first then immediately resolves and returns undefined, which kicks off the fulfillment handler for the second then.
If you want to execute the fulfillment handler for the second then only after the first fulfillment handler has completed, it needs to return a Promise.
Promise.resolve(42).then(function(){
return new Promise(function(resolve, reject){
window.setTimeout(function(){
console.log(window.performance.now());
resolve();
}, 1000);
});
}).then(function(){
window.setTimeout(function(){
console.log(window.performance.now());
}, 1000);
});Notice that it's more than just wrapping your code in a new Promise:
return new Promise(function(resolve, reject){...})You'll need to add a resolve() expression, otherwise it will hang.
Returning the appropriate Promise
This won't work as intended:function myPromise() {
var url = 'someURLHere';
return Promise.resolve(window.setTimeout(function(){console.log('myPromise resolved');}, 2000));
}
myPromise().then(function(output){
console.log(output);
console.log('end');
});This returned promise in myPromise is immediately resolved; the value that is passed on is the result of window.setTimeout, specifically the timeoutID. The fulfillment handler would immediately fire, outputting end, then after two seconds you will get confirmation that myPromise has resolved.
Instead, try this:
function myPromise() {
var url = 'someURLHere';
return new Promise(function(resolve) {
window.setTimeout(function() {
console.log('myPromise resolved');
resolve();
}, 2000)
});
}
myPromise().then(function(output){
console.log(output);
console.log('end');
});