In 2010, I had this conversation with my prolific colleague Mr. Ajax:
Hey, would you fetch some data from this URL for me, please?
I’m on it! Just give me a success callback so I can let you know when I’m done.
OK, here you go. Thanks.
Oh, and you should give me an error callback, too. You know, just in case.
Good point. Anything else?
Hey, I noticed that there’s some code duplication between those two callbacks! You could move that into a third always callback.
(impatiently) Alright, I’ll refactor them. Tell you what: why don’t you run now, and I’ll give you the callbacks later?
(irately) What do I look like, an EventEmitter?
Thankfully, jQuery 1.5 changed Mr. Ajax’s need-it-now attitude. All of the Ajax functions you know and love ($.ajax, $.get, and $.post) now return Promises. A Promise is an object that represents a task with two possible outcomes (success or failure) and holds callbacks that fire when one outcome or the other has occurred. For example, under jQuery 1.4, I’d have had to write this:
Promises/get-1.4.js | |
| $.get('/mydata', { |
| success: onSuccess, |
| failure: onFailure, |
| always: onAlways |
| }); |
But under jQuery 1.5+, I can write this instead:
Promises/get-1.5.js | |
| var promise = $.get('/mydata'); |
| promise.done(onSuccess); |
| promise.fail(onFailure); |
| promise.always(onAlways); |
You might wonder what’s so great about this change. Why would you want to attach a callback after an Ajax call has fired? In a word: encapsulation. If an Ajax call has multiple effects (triggering animations, inserting HTML, locking/unlocking user input, and so on), it’s awkward for the part of your app that’s making the request to handle all of them.
It’s much more elegant to pass a Promise around. By passing a Promise, you’re announcing, “Something you might be interested in is happening. If you want to find out when it’s done, just give this Promise a callback.” And like an EventEmitter, a Promise allows you to bind handlers to the same event as many times as you like (stacking). That makes it a lot easier to reduce code duplication when some small piece of functionality (like a “Loading” animation) is shared across several Ajax calls.
But the biggest advantage of using Promises is that you can easily derive new Promises from existing ones. You might ask two Promises representing parallel tasks to give you a Promise that will inform you of their mutual completion. Or you might ask a Promise representing the first task in a series to give you a Promise representing the final task in the series. As we’ll soon see, these operations come naturally with Promises.
3.15.206.105