Page 1 of 1

Cool Javascript design pattern: Promises

Posted: Fri Sep 21, 2012 1:39 am
by Jackolantern
Honestly, I had never heard of Promises until I started digging into Windows 8 app development, which uses Promises heavily. In fact, in Windows 8 apps, Promises pretty much take the place of the standard callback style of Javascript, and I have to say (in my opinion) it is a huge improvement and really helps you manage the asynchronous aspects of Javascript development. Here is an example from the MSDN documentation:

Code: Select all

myWebService.get("http://www.example.com")
    .then(function(result) { 
        return myDb.add(result); 
    })
    .then(function() {
        console.log('data successfully saved');
    }, function(error) {
        console.log('an error occurred while saving:');
        console.dir(error);
    });
You can see maybe a bit of benefit in added clarity, but that is of course up to personal taste. I personally find this a much better structure than the "callbacks of callbacks of callbacks..." style of vanilla asynchronous Javascript. But where Promises really start to show a lot of benefit is when it comes to synchronizing callbacks so that one will not fire until any others it relies on have fired as well. This is what leads to the very messy looking nested callback structure. Here is another example from MSDN that uses the join() function to basically group all of the actions together so the callback (or "promise"/"then function" in the Promise pattern) for the whole process will not fire until all have completed (note webService.get() is a made-up function for the example). What is happening on the line that starts "var promises" is that the Array.prototype.map() function is being used to convert the array of webservice URLs into an array of promises, so it is basically turning them into little, self-contained tasks that also can handle callbacks:

Code: Select all

function loadData() {
    var urls = [
        'http://www.example.com/',
        'http://www.example.org/',
        'http://www.example.net'
        ];
        
    var promises = urls.map(function (url) {
        return myWebService.get(url);
    });

    WinJS.Promise.join(promises).then(function () {
        //do the aggregation here.
    });
}
There are even more complex things that can be done with Promises. With names like "join", it sounds like the creator of the pattern had a lot of experience with traditional multithreading, and wanted to bring more of the fine-grained control tricks in multithreading to asynchronous Javascript (which I am totally cool with :D). One example would be preventing a callback from firing until another callback in a separate callback chain has completed, which is typically quite messy and error-prone, not to mention that the old techniques for dealing with these situations force a connection between separate parts of your code with little visual relation between them.

Here is the Common JS wiki page that discusses Promises, and they are the ones who maintain the pattern and its several different forms (Windows 8 apps with JS use Promises/A).

And, probably the most important part of this for most people on these forums, here is a link to Node-Promise, which is a Node.js Promises module. There is also another one called Futures.

If anyone is really struggling on how to structure their applications in Node.js (which is nearly 100% asynchronous), I highly suggest to check it out. It may really pay off :idea:

Re: Cool Javascript design pattern: Promises

Posted: Fri Sep 21, 2012 1:43 am
by hallsofvallhalla
Oh wow, this is very kewl indeed. I could have used this several times already. What browsers support this?

Re: Cool Javascript design pattern: Promises

Posted: Fri Sep 21, 2012 3:18 am
by Jackolantern
Right now no browser supports it natively since it is a pattern. However, there are talks already about it possibly superseding the current callback structure or (more likely) being implemented as an alternative.

However, FuturesJS is a library that gives full, robust Promises support, and the Github page includes a section on getting it to work browser-side. I just actually found this out, because I was really looking at it for Node and Windows 8 apps. There are a couple of other scripts you have to include to support all dependencies, but he includes them all in the Futures download and provides a sample page header that correctly includes them all in the Github page. This one library can work for Node and browser! That is pretty cool. :mrgreen:

EDIT: Actually, I wonder if IE 10 may support promises out of the box since they are such an integral part of Windows 8 apps, and the IE 10 JS engine is powering the JS side of Windows 8 apps. If it does support them, other browsers may follow soon.

Edit2: Although it is a bit old, here is an interesting question on Stack Overflow about how to use Promises client-side. Of course anything about the browsers would be out-dated, but any libraries or other solutions mentioned there would likely be quite mature and stable now (Futures is mentioned there).