Promises are an elegant way of providing for the handling of the future completion of an action in JavaScript. You will be familiar with the concept of a callback. This allows your app to get on with something else whilst an asynchronous activity, such as user input or an ajax request is taking place, and then deal with the results when it’s over .

The problem with callbacks is that your code very quickly becomes unreadable if you have a few activities happening simultaneously. It also encourages namespace pollution as you try to keep track of asynch results. On this site  pretty much all webapps use promises to handle execution orchestration.

To get started, here’s a very simple example, getting JSON data from Google apps script (as described in Using ScriptDB as a noSQL database for non-Google Apps Script clients)

The setup

google.load("jquery", "1");
google.setOnLoadCallback( function() {
    initialize().then ( function (control) {
        renderScriptDb(control);
    });
});

The thing about using promises is that reading it should explain what it’s doing. 
Once jquery is loaded, run an initialize() function, and then render the results. The key here is that .then() is like a callback – it only gets executed once initialize() has been deemed ‘resolved’. No different than a callback really, except you are controlling the completion of initialize() – which of course doesn’t have to even be asychronous.

I find myself using promises as a matter of course – meaning that if functions do grow into something asynchronous at some time in the future, no main code changes will be required.

The other benefit is that you can combine promises without getting into the kind of spaghetti that multiple callbacks would generate – but that’s another snippet for another day.

The data access

Here I’m just setting up the url for the data access I want to make.

function initialize() {
    var s = [];
    s.push( 
         "https://script.google.com/a/macros/mcpher.com/s/AKfycbzhzIDmgY9BNeBu87puxMVUlMkJ4UkD_Yvjdt5MhOxR1R6RG88/exec"); 
    s.push ("?type=jsonp");
    s.push ("&source=scriptdb");
    s.push ("&module=accounts");
    s.push ("&library=useMultipleDB");
    var query = {data:{customer:{name:"john"}}};
    s.push ("&query=" + encodeURIComponent(JSON.stringify(query)));
    return getPromiseData (s.join(''));
}

Note that I return the deferred promise returned by this function

function getPromiseData(url,proxyUrl){
        var deferred = $.Deferred();
        var u = proxyUrl ? proxyUrl + "?url="+encodeURIComponent(url) : url + "&callback=?";
    
        $.getJSON(u, null, 
            function (data) {
                deferred.resolve(data);
            })
            .error(function(res, status, err) {
                deferred.reject("error " + err + " for " + url);
            });
            
      return deferred.promise();
    }

Here I create a $.Deferred(), which is jquery’s implementation of promises. The regular callback from getJSON will either succeed – where I resolve the promise and return the data, or fails, where i reject the promise and return the error.

Snippet of the day archive

There are various snippets throughout this site. Some of them have been categorized and some not. I’ll use the page for my ‘snippet of the day’ and change them when I remember. You can find other assorted snippets here and here.