51

Possible Duplicate:
What are the differences between Deferred, Promise and Future in Javascript?

Lately I've been making an effort to improve the quality of my JavaScript applications.

One pattern I've adopted is to use a separate "data context" object to load data for my application (previously I was doing this directly in my view models).

The following example returns data that is initialized on the client:

var mockData = (function($, undefined) {

    var fruit = [
        "apple",
        "orange",
        "banana",
        "pear"
        ];

    var getFruit = function() {
        return fruit;
    };

    return {
        getFruit: getFruit
    }
})(jQuery);

In most cases we'll be loading data from the server so we can't return an immediate response. It seems I have two options for how we handle this in our API:

  1. Using a callback
  2. Returning a promise.

Previously I'd always used the callback approach:

var getFruit = function(onFruitReady) {
    onFruitReady(fruit);
};

// ...

var FruitModel = function(dataContext, $) {
    return {
        render: function() {
            dataContext.getFruit(function(fruit) {
                // do something with fruit
            });
        }
    };
};

However, I can see how it's possible to end up in callback hell, especially when building complex JavaScript applications.

Then I came across the Promises design pattern. Instead of requiring the caller to supply a callback, I instead return a "promise" that can be observed:

var getFruit = function() {
    return $.Deferred().resolve(fruit).promise();
};

// ...
dataContext.getFruit().then(function(fruit) {
    // do something with fruit
});

I can see obvious benefits of using this pattern, especially since I can wait on multiple deferred objects which could be very useful when loading initialization data for a single page application.

However, I'm keen to understand the pros and cons of each pattern before I start to use either in anger. I'm also interested in whether this is the direction other libraries are going in. It seems to be the case with jQuery.

Here's a link to the fiddle I'm using for testing.

Community
  • 1
  • 1
Ben Foster
  • 34,340
  • 40
  • 176
  • 285
  • 4
    Well good news: the jQuery ajax APIs *already* return Promises! – Pointy Jan 02 '13 at 19:12
  • [Read up on the mechanism here.](http://api.jquery.com/jQuery.ajax/#jqXHR) – Pointy Jan 02 '13 at 19:14
  • Yes, this is how I came across the pattern in the first place as I was looking for a way to abstract my ajax calls. – Ben Foster Jan 02 '13 at 19:15
  • i think callbacks are a little bit faster, but i really like your question and am interested in an answer! – hereandnow78 Jan 02 '13 at 19:16
  • Ah. Well what I mean is that you don't really need to add much; the return values from those calls are ready-to-use, so it's simply a matter of getting out of the habit of passing in "success" callbacks and getting *into* the habit of calling `.done()` etc. – Pointy Jan 02 '13 at 19:16
  • @jbabey I'm asking what the pros and cons are of using callbacks *vs* Deferred/Promise, so quite a different question. – Ben Foster Jan 02 '13 at 19:34
  • angularjs has a nice concept around retrieving server side resources: http://docs.angularjs.org/tutorial/step_05 – Amir Jan 02 '13 at 19:35
  • @jbabey not a duplicate: deferred/promise/future belong to the promises pattern, the OP is asking for a comparison with direct callbacks. – Christophe Jan 02 '13 at 19:36
  • @BenFoster the question is poorly named - read the answers as they appear to be answering exactly what you are asking. "Rather than directly passing callbacks to functions, something which can lead to tightly coupled interfaces, using promises allows one to separate concerns for code that is synchronous or asynchronous." – jbabey Jan 02 '13 at 19:36
  • @jbabey This question is fundamentally different from the other flagged as a "duplicate". Callbacks are a completely different mechanism than are futures/promises, and marking this question as a duplicate creates serious, detrimental confusion for anyone trying to learn about the differences between these concepts. – Levi Lindsey Jun 17 '14 at 20:12
  • Ref: http://softwareengineering.stackexchange.com/questions/302455/is-there-really-a-fundamental-difference-between-callbacks-and-promises – Mahesh K Oct 26 '16 at 04:33

2 Answers2

18

Promises also rely on callbacks behind the scene, so it's not really one vs. the other.

The benefit of callbacks is that they are easy to implement with plain JavaScript (for example in ajax calls).

Promises require an additional abstraction layer, which usually means that you'll rely on a library (not an issue in your case as you are already using jQuery). They are perfect when you deal with multiple async calls in parallel.

Christophe
  • 27,383
  • 28
  • 97
  • 140
  • 9
    Note that as of March 2014, browsers have started implementing native promises, so my statement only holds true for polyfills. – Christophe Apr 25 '14 at 02:03
3

From reading the jQuery docs that @Pointy linked to, it sounds like the difference is that the Deferred API allows you to specify more than one function to be called when your request completes:

As of jQuery 1.5, the error (fail), success (done), and complete (always, as of jQuery 1.6) callback hooks are first-in, first-out managed queues. This means you can assign more than one callback for each hook. See Deferred object methods, which are implemented internally for these $.ajax() callback hooks.

See also: deferred.then()

Max Fellows
  • 382
  • 3
  • 9
  • 1
    It's not that Deferreds/promises *allow* you to specify more than one function to be called, so much as they make doing so *easier*. Particular features are that (a) functions can be added (with eg. `.done()` or `.fail()`) anywhere in the code, subject only to the Deferred/promise being within scope, and (b) functions added after a Deferred has been resolved/rejected will fire immediately. By exposing its internal `.Callbacks()` utility, jQuery makes this type of functionality *possible* without using Deferreds/promises, but they take the pain out of the coding/debugging. – Beetroot-Beetroot Jan 02 '13 at 23:47