0

NOTE: I am using jQuery version 1.7.2.

I'm trying to understand jQuery promises and deferred objects.

I have the following code:

var that = this;
var dataRetrieved = that.retrieveData();
$.when(dataRetrieved).then(function(data) {
   that.formatDataForTemplate(data);
});

retrieveData: function () {
  if ( // condition A ) {
    return window.data.conditionA;
  } else if (// condition B) {
    return window.data.conditionB;
  } else {
    this.fetch({
        success: function (status, response) {
            return response;
        }
    });
  }
}

basically, I want to pass in whatever data is returned from retrieveData into the .then() function, but it doesn't seem to work. the retrieveData() function is being called (checked with a console.log), however the formatDataForTemplate is not being called.

retrieveData() may return data instantly, or may return data from an AJAX query (this.fetch({});). I need the .then() to only fire once data has been returned from retrieveData.

I think I'm just not understanding promises clearly. How can I make my code accomplish what I'm trying to do?


EDIT: hm, still not quite getting the hang of it.. Here's my updated version. I'm trying to figure out how to return a promise that has been resolved with my data.

var that = this;
var dataRetrieved = that.retrieveData();
dataRetrieved.then(function(data) {
    that.formatDataForTemplate(data, that.get('template'));
});


retrieveData: function () {

    var that = this;

    if (window.settings.preview === 'true') {
        return $.Deferred(function(def) {
            def.resolveWith(window.settings.previewData);
        });
    }

    // else if mock (during dev), use mock data.
    else if (this.get('is_mock')) {
        var mocked_data = {
            "title":"Mock Title",
            "description": "Mock Description"
        };
        // return mocked_data;
        return $.Deferred(function(def) {
            def.resolveWith(mocked_data);
        });
    }

    // else, hit API like normal.
    else {
        return $.Deferred(function (def) {
            that.fetch({
                success: function (status, response) {
                    def.resolveWith(response);
                }
            });
        });
    }
},
tdc
  • 5,174
  • 12
  • 53
  • 102
  • `retrieveData` would of course need to return a promise to be used with $.when, otherwise $.when wouldn't be able to tell when it should complete. – Kevin B Aug 05 '15 at 20:18
  • @KevinB - Sorry I'm dumb, can you elaborate? How do I return both the data I need + a promise in `retrieveData`? – tdc Aug 05 '15 at 20:19
  • you would return a promise that will later be resolved with the data that you need. – Kevin B Aug 05 '15 at 20:19
  • Could you post an example of what you mean? I'm having a hard time visualizing. – tdc Aug 05 '15 at 20:25

1 Answers1

-1

For this to work, retrieveData would need to return a promise that is resolved with the data.

var that = this;
var dataRetrieved = that.retrieveData();
dataRetrieved.then(function(data) {
   that.formatDataForTemplate(data);
});

retrieveData: function () {

  if ( // condition A ) {
    return window.data.conditionA; // this should be a promise that has been resolved with data
  } else if (// condition B) {
    return window.data.conditionB; // this should be a promise that has been resolved with data
  } else {
    var that = this;
    return $.Deferred(function (def) {
        that.fetch({
            success: function (status, response) {
                def.resolveWith(response);
            }
        });
    });
  }
}
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Thanks for the help. I've edited my original question. I'm trying to return a `$.Deferred()` which contains a resolution with my data but doesn't seem to be working as I expected. – tdc Aug 05 '15 at 20:42
  • As far as I can tell it's firing `retrieveData()` however `formatDataForTemplate()` is not getting called within the `.then()` anonymous function. – tdc Aug 05 '15 at 20:46
  • add a second function to .then, is it being called? any console errors? – Kevin B Aug 05 '15 at 20:46
  • Doesn't appear to be. – tdc Aug 05 '15 at 20:47
  • is `return $.Deferred(function(def) { def.resolveWith(***my data here***); });` the wrong syntax? – tdc Aug 05 '15 at 20:50
  • Looks right to me. though, could use a .promise() at the end. should have worked without it tho – Kevin B Aug 05 '15 at 20:50
  • Hm. Well, the first 2 blocks in `retrieveData` just return a local object, whereas the third performs an ajax query (Backbone's `fetch()` method). Don't know if that affects anything. Didn't work when I added `.promise()` to the end of the `$.Deferred()` – tdc Aug 05 '15 at 20:52