Starbeamrainbowlabs

Stardust
Blog

Tutorial: Javascript Promises: There and Back Again in Half the Time

If you are familiar with javascript, the chances are that you have found this post. I found it to be a great introduction to promises in javascript, but I also found the post to be rather long and not good as a reference. This post, however is an attempt to condense the information found in the tutorial from html5rocks (Update! HTML5 Rocks has been turned into the Google Developers Web Fundamentals) into a nice neat package that is not only useful as a tutorial, but also useful as a reference.

The Problem and the Solution

When performing asynchronous tasks in javascript, you usually have to use callbacks and event listeners. This can quickly get unwieldy and difficult to understand. Promises were invented to rectify this problem. They allow you to chain function calls asynchronously - which generally cleans up your code and makes it easier to read:

function get(url)
{
    return new Promise(function(resolve, reject) { //important!
        var ajax = new XMLHttpRequest();
        ajax.onload = function() {
            if(ajax.status >= 200 && ajax.status < 300)
                resolve(ajax.response); //return the response
            else
                reject(ajax.response);
        }
    });
}

The important bit is the returning of a promise instead of actually performing the action requested. When creating a promise, a function is taken as the only argument. This function is then called with 2 arguments: a function that should be called upon success (usually called resolve()), and a function that should be called upon failure (usually called reject()).

Any number of asynchronous actions can be performed before either resolve() or reject() are called, but I would adivse that you put one async call in each promisified function.

The resolve() and reject() functions take a single argument: the value that should be passed onto the next function in the chain.

and then....

Once a promise has been returned, an API is exposed that allows you to chain functions together in a long string through the function then():

//                         then() adds a function to the chain
//                                        |--------v
get("https://starbeamrainbowlabs.com/humans.txt").then(function(response) {
    //we got a response :D
    console.info("Got response", response);
}, function(error) {
    //something went wrong :(
    console.error("Something went wrong:", error);
});

then() takes a pair of functions as it's arguments. The first function is called upon success (and passed the value that was passed to resolve()), and the second (optional) function is called upon failure (and passed the value that was passed to reject()).

Repetition

The best part of javascript promises is the ability to chain then() as many times as you like:

get("https://example.com/urls.txt").then(function(text) {
    return text.split("\n");
}).then(function(lines) {
    lines.forEach(function(url) {
        get(url).then(function(response) {
            console.log("got", url, "with text", response);
        });
    });
});

Infinite chaining

The problem with the above is that lots of ajax calls a being made at once. If you used this in your next big web app, it could bring your server down having all the requests being sent out at once.

There is, however, a solution to this too. We can process each value in an array one at a time using Array.reduce():

get("https://example.com/urls.txt").then(function(text) {
    return text.split("\n");
}).then(function(lines) {
    lines.reduce(function(sequence, url) {
        return squence.then(function() {
            return get(url);
        }).then(function(response) {
            console.info("got", response);
        });
    }, function() { return new Promise(function(resolve) { resolve(); }); });
});

In this way, a new promise is created that resolves straight away (you can also use the Promise.resolve function is a shortcut here, but some implementations - especially Node.JS based ones - don't support this), and a promise for each url are then tacked onto the end of it. These are then called in a row - once th eprevious ajax request has completed, the next one will be sent. This can also be helpful when you are fetching content from a list of urls and you want them to be kept in order.

Conclusion

Promises are cool - they let you simplify complex asynchronous code. You can chain them with then() as many times as you like - and you can use Array.reduce() to chain calls that iterate over each value in an array.

So there you have it! A short tutorial on javascript promises. If you do not understand anything in this tutorial, please leave a comment below and I will try to answer your question.

Found a mistake? Leave a comment below.

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blender blog bookmarklet booting bug hunting c sharp c++ challenge chrome os cluster code codepen coding conundrums coding conundrums evolved command line compilers compiling compression containerisation css dailyprogrammer data analysis debugging demystification distributed computing dns docker documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions freeside future game github github gist gitlab graphics hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs learning library linux lora low level lua maintenance manjaro minetest network networking nibriboard node.js open source operating systems optimisation own your code pepperminty wiki performance phd photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference releases rendering resource review rust searching secrets security series list server software sorting source code control statistics storage svg systemquery talks technical terminal textures thoughts three thing game three.js tool tutorial tutorials twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 worldeditadditions xmpp xslt

Archive

Art by Mythdael