JS Promises in Five Quick, Dirty, and Insufficient Minutes
You may have heard about the benefits of using promises, but don’t yet know what they are or how they can be of use to you. In one sentence, promises are objects used for asynchronous actions that resolve in their own time and can have more actions (synchronous or asynchronous) chained onto them that fire upon and are sensitive to the outcome of each resolution.
First, most browsers don’t support the standardised Promises/A+ behavior yet, so pop in this tiny polyfill.
Now, let’s make a function that returns a promise. It will look like this:
function test () { return new Promise(function(resolve, reject) { //do some stuff, possibly asynchronous stuff //on success, call resolve(your object's new value) //on fail, call reject(an Error object) }; }
Say you want to make an AJAX request. That might look like this:
function ajax (url) { return new Promise(function(resolve, reject) { var request = new XMLHttpRequest(); request.open('GET', url); request.onload = function() { if (request.status === 200) { resolve(request.response); } else { reject(Error(request.statusText)); } }; request.onerror = function() { reject(Error("Network fault!")); }; request.send(); }); }
As you can see, calling ajax() creates a new promise object, which has two methods: resolve and reject. An anonymous ajax() therefore becomes a promise object which becomes data in its own time, and can be manipulated with chained actions.
The chained action you want is .then(success, failure);, where success and failure are actions to complete as soon as the promise is fulfilled or rejected.
ajax('../text.json').then(function(response) { //Success! Do something with the response. return JSON.parse(response); }, function(response){ //Failure. Oh well. return response; });
Chain some more on there, and keep in mind that success and failure actions are completely optional–we’ll be omitting failure actions here. Check out how the object that .then operates on changes depending upon what happens asynchronously, then .then allows us to time our actions to exactly when these changes happen. The anonymous object can be a Promise, some JSON, a string, and then go back to being a Promise, giving us abilities like sequential loading.
ajax('../captions.json').then(function(response) { return JSON.parse(response); }).then(function(parsedJSON) { return parsedJSON.caption[0]; }).then(function(firstCaption) { document.getElementById('caption').innerHTML = firstCaption; }).then(function() { return ajax('../subcaptions.json'); }).then(function(subcaptions) { document.getElementById('subcaption').innerHTML = JSON.parse(subcaptions).subcaption[0]; });
And that’s that. Is there a lot more to it? Dear god, yes. This ought to get you started, though.