The DeftJS framework for ExtJS and Sencha Touch has been updated to include a Promise API. John and I are already at work on updated docs that cover these (and other) new features, but I wanted to post an entry to explain some of the benefits that Promises bring to the table.
If you aren’t familiar with Promises, perhaps the Wikipedia definition will help:
In computer science, future, promise, and delay refer to constructs used for synchronizing in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.
Definitions are nice, but I find examples to be much more useful to aid in understanding something. So lets jump in and look at some code.
A Common Example of an Asynchronous Call in ExtJS
Say I’m building an ExtJS application that uses DeftJS. I’ve tried to separate my concerns, so I’ve created a ViewController to manage a UI component, and a Service class to encapsulate interaction with some of my Stores, AJAX logic, and external resources. My ViewController might have a loadCompanies() method like this, which calls an injected Service object. The Service, in turn, asks a CompanyStore to load its data:
“OK,” you might think, “that doesn’t look too bad.” And on the surface, it isn’t too bad. But let’s dig further. Stores aren’t the only option ExtJS provides for leveraging AJAX. It also has an Ajax class which can be used when a Store won’t fit your needs, or when you need more control over the handling of the results. Let’s look at the same general process I showed above, but using the Ajax class:
Notice anything disconcerting? The two calls to my Service method have different ways of defining the callbacks: one passes a “callback” property, but the other passes separate “success” and “failure” callbacks. The code in the controller is coupled to the way the service loads data. Worse, if you have a number of these sorts of service calls, with mixed sets of arguments, things get pretty ugly. Luckily, using a Promise offers a better way.
An Asynchronous Call using a Promise
Here is the ViewController code, along with examples of Service methods using both a Store load and an AJAX request:
Excellent. Now the ViewController method looks exactly the same, regardless of what the Service is doing! The Service methods create a Deferred object to wrap the async call, and then return a Promise back to the ViewController. Also, note that I can use the always() method provided by the Promise to run code regardless of whether it succeeded or failed. So what’s the difference between a Deferred and a Promise? To help explain the difference, I created this simple diagram:
So the general idea is that the Deferred is “private”, and actually wraps the async call. The Promise is the “public” view of the state of the Deferred. It won’t allow you to resolve or reject its state, but it will allow you to attach callbacks that are invoked when the state of the Deferred changes.
Multiple Asynchronous Calls
So we’ve seen how a Promise can help standardize the way things interact with async processes, and that’s great. But Promises can do a lot more. For example, let’s say at app startup I need to load both a list of companies and a list of featured products. I can’t proceed until both are finished. One way (a very bad way) this could be done is:
I think we can all agree that’s just horrible. There are actually some slightly less horrible ways that could be done, but any way you slice it, it’s not very pretty. So how can using Promises help? How about:
As you can see, I’m taking the two Promises returned by loadCompanies() and loadFeaturedProducts(), and wrapping them in another Promise. That Promise will resolve or reject based on the state of the two Promises it is wrapping. Even better, we can once again see that the code in the ViewController stays exactly the same as in the previous examples! This is a far better option than the other hackish ways one might come up with to execute multiple calls in a single group.
I’ve shown how Promises can bring consistency to code that has to deal with asynchronous behavior. The ability to treat multiple asynchronous calls as a single unit just adds more icing to the cake. Promises are useful in even more ways, but I’ll stop rambling for now. If you use ExtJS and are using (or considering) DeftJS, you’ll definitely want to give the Promises API a try.