Docs
Everything You Need to Know
Promises
Use
ECMAScript 6 Promises provide the following interface:
- Promise
- Promise.then()
- Promise.resolve()
- Promise.reject()
- Promise.catch()
- Promise.race()
- Promise.all()
If you are familiar jQuery's Deferred object, this will not look too foreign. Except for the last two: race and all. These have no equivalent with typical deferreds. They are features specific to ECMAScript promises.
The Promise Interface
An ECMAScript 6 promise is created with the "new" keyword. This returns an instance of the Promise object.
var myPromise = new Promise();
When you create a promise, you can also provide a callback. This will be able to handle two arguments: resolve and reject:
var myPromise = new Promise(function(resolve, reject) {
var value;
// Do something to get value;
// ...
// Then test value to determine how to handle the promise:
if (value === 'good') {
resolve(value);
} else {
// When you reject the promise,
// you also get the reason it failed,
// which you can choose to output if you want:
reject(reason);
}
});
Then
Promises provide several methods allowing us to do useful things. The way you'll most like use promises is with the then
method. This method can take up two two callbacks–one for success and one for failure.
// Create an instance of a promise:
var myPromise = new Promise(function(resolve, reject) {
// Resolve the promise:
resolve('Success!');
// or reject it:
// reject('Lost in Space!');
});
myPromise.then(function(value) {
// Success:
console.log(value);
},
// Opps! There was a problem:
function(reason) {
console.log(reason);
});
As you can see in the above code, then
can handle two callbacks, one for success and another optional one for failure. You can just provide a single callback to handle the success. That's up to you. If you want, you could return whatever value you get in your success callback, which allows you to chain a second function. Read the next part on Multiple Thens for more information.
Multiple Thens
The then
method always returns a promsie. This means that you can chain multiple thens together. This allows you to break your code up into more logical blocks. This also helps you to avoid one of JavaScript development's worse patterns–the pyramid of doom–deeply nest series of callbacks.
var myPromise = new Promise(function(resolve, reject) {
resolve(1);
});
myPromise.then(function(value) {
console.log(value); // 1
// Return the value:
return value + 1;
})
.then(fuction(value) {
console.log(value) // 2
})
Resolve
We can resolve a promise at any time using the resolve
method on the static Promise object. Once we execute the resolve method, the promise is disposed of.
// Define an alias for the resolve callback:
var fulfill;
new Promise(function (resolve, reject) {
fulfill = resolve;
}).then(function(value) {
equal(value, 5, 'Promise fulfilled with Promise should resolve to actual value');
start();
});
fulfill(Promise.resolve(5));
Reject
Like the resolve example above, we can similarly reject a promise using its method on the static Promise object. In this example we pass a value that gets returned with the rejection:
var fulfill;
new Promise(function (resolve, reject) {
fulfill = resolve;
}).catch(function(value) {
console.log(value);
});
fulfill(Promise.reject(5));
Catch
We can handle errors and exceptions using the catch
method. This enables us to have a series of thens that only handle success situations. ECMAScript promise pass any exception along until their is some callback to handle it.
var myPromise = new Promise(function(resolve, reject) {
resolve("Success!");
});
myPromise.then(function(value) {
console.log(value); // Success!
throw "Oops! Something went wrong.";
})
.catch(function(error) {
console.log(error); // Oops! Something went wrong.
})
Race
Sometimes you may need to execute several operations and any one of them could finish first. You want to take the result of the first to finishing, ignoring the others. ECMAScript promises enable this with the race
method. This expects an array of promises as its argument.
var f1, f2, f3;
var p1 = new Promise(function(f, r) { f1 = f; });
var p2 = new Promise(function(f, r) { f2 = f; });
var p3 = new Promise(function(f, r) { f3 = f; });
Promise.race([p1, p2, p3]).then(function(value) {
console.log('Promise.race() should resolve to: ' + value);
});
// Execute the second:
f2(2);
All
Unlike with race conditions, sometimes you want to execute a number of things and wait until they are all done before doing anything. In those cases you can use the all
method. This expects an array of promises as its argument.
var f1, f2, f3;
var p1 = new Promise(function(f, r) { f1 = f; });
var p2 = new Promise(function(f, r) { f2 = f; });
var p3 = new Promise(function(f, r) { f3 = f; });
Promise.all([p1, p2, p3])
.then(function(value) {
console.log(value);
});
// Execute theme in opposite order:
f3(3);
f2(2);
f1(1);