March 9, 2016 by Christoff Truter JavaScript ES6
A Promise acts like a placeholder for an asynchronous operation that hasn't completed yet, its aim is to give us back the things we "lost" (or never had for that matter) when writing asynchronous code opposed to synchronous code.
"Lost" in regards to logical flow (code structure) and language fundamentals, e.g functional composition (return) and error bubbling (throw).
Have a look at the following run-of-the-mill synchronous snippet:
var args = [];
function one() {
return 1;
}function two() {
return 2;
}function three() {
return 3;
}
args.push(one());
args.push(two());
args.push(three());
console.log(args);
function one(_return) {
setTimeout(function() {
_return(1);
}, 200);
}function two(_return) {
setTimeout(function() {
_return(2);
}, 150);
}function three(_return) {
setTimeout(function() {
_return(3);
}, 100);
}
one(function(arg) {
args.push(arg);
two(function(arg) {
args.push(arg);
three(function(arg) {
args.push(arg);
console.log(args);
});
});
});
function two(_return, _failed) {
setTimeout(function() {
try {
throw new Error('Oh no!');
_return(2);
} catch (e) {
_failed(e);
}
}, 150);
}
one(function(arg) {
args.push(arg);
two(function(arg) {
args.push(arg);
three(function(arg) {
args.push(arg);
console.log(args);
});
}, function(error) {
console.log(error);
});
});
Ok, so lets clean this up a bit using promises.
Initially I was going to do a little write up on JQuery's broken promises (see what I did there?) but decided to give it a skip, there is a link further down that goes into great detail about it (even the 2.x branch is broken).
Instead I am going to use a library called Q (which is fully Promise/A+ Compliant).
Observe the following snippet:
function asyncOne() {
return Q.promise(function(resolve) {
setTimeout(function() {
console.log(1);
resolve(1);
}, 200);
});
}function asyncTwo() {
return Q.promise(function(resolve) {
setTimeout(function() {
console.log(2);
resolve(2);
}, 150);
});
}function asyncThree() {
return Q.promise(function(resolve) {
setTimeout(function() {
console.log(3);
resolve(3);
}, 100);
});
}
var args = [];
var addResult = function(arg) {
args.push(arg);
};
asyncOne()
.then(addResult)
.then(asyncTwo)
.then(addResult)
.then(asyncThree)
.then(addResult).then(function() {
console.log(args);
});
function asyncTwo() {
return Q.promise(function(resolve, reject) { // throw new Error('Oh no!'); Will return promise
setTimeout(function() { // throw over here will fail since it is out of process, // therefore can't return a promise.
reject('Oh no!');
console.log(2);
resolve(2);
}, 150);
});
}
var args = [];
var addResult = function(arg) {
args.push(arg);
};
asyncOne()
.then(addResult)
.then(asyncTwo)
.then(addResult)
.then(asyncThree)
.then(addResult)
.then(function() {
console.log(args);
}).catch(function(error) {
console.log(error);
});
Q.all([asyncOne(), asyncTwo(), asyncThree()]).then(function(results) {
console.log(results);
});
function asyncOne() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log(1);
resolve(1);
}, 200);
});
}function asyncTwo() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log(2);
resolve(2);
}, 150);
});
}function asyncThree() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log(3);
resolve(3);
}, 100);
});
}
var args = [];
var addResult = function(arg) {
args.push(arg);
};// Run sequentially
asyncOne()
.then(addResult)
.then(asyncTwo)
.then(addResult)
.then(asyncThree)
.then(addResult)
.then(function() {
console.log(args);
}).catch(function(error) {
console.log(error);
});
// Run in parallel
Promise.all([asyncOne(), asyncTwo(), asyncThree()]).then(function(args) {
console.log(args);
});
You're Missing the Point of Promises
Javascript promises and why JQuery implementation is broken
JavaScript Promises There and back again