Search code examples
javascriptmarionettejquery-deferredbackbone-events

Callback response/status for Backbone.Wreqr request-response handler when it is done


The usual way of using jquery deferred.resolve method is by calling it when you have a callback function which gives you a response that they are fully loaded, as in this case the xhr add an event listener when it is loaded and provides the xhr response to deferred.resolve.

The following code is copied from one of the example. http://www.danieldemmel.me/blog/2013/03/22/an-introduction-to-jquery-deferred-slash-promise/

function getData(){      
  var deferred = $.Deferred();           
  XMLHttpRequest xhr = new XMLHttpRequest();
  xhr.open("GET","data",true);            
  xhr.addEventListener('load',function(){
    if(xhr.status === 200){          
      deferred.resolve(xhr.response);
    }else{          
      deferred.reject("HTTP error: " + xhr.status);
    }
  },false)             
  xhr.send();
  return deferred.promise();
}

My current code which retrieves data using Marionette request-response handler. Is there anyway i can get a callback response from the following request

function getData(activityID) {
  var defer = $.Deferred();
  require(["entities/element/element_collection"], function() {
    var fetchData = App.request("element:entities:initialize", activityID);
    //Example code scenario
    // How do i know my request is being fulfilled? and used Deferred.resolve accordingly.
    //maybe something as follows?
     fetchData.success(function(response){
        defer.resolve(response);
     }); 
     //Example code scenario 

  });

  return defer.promise();
};

The request handler basically will be giving back a Backbone collection which will be generated by passing a collection of objects into the new Backbone Collection.


Solution

  • If (as it would appear) require() is asynchronous and App.request() is synchronous, then you could write your code as follows :

    function getData(activityID) {
      var defer = $.Deferred();
      require(["entities/element/element_collection"], function() {
        var fetchData = App.request("element:entities:initialize", activityID);
        defer.resolve(fetchData);
      });
      return defer.promise();
    };
    
    getData(activityID).done(function(fetchData) {
        //do awesome stuff with fetchData here
    });
    

    or, depending on how much/little you want to do in getData(), as follows :

    function getData() {
      var defer = $.Deferred();
      require(["entities/element/element_collection"], defer.resolve);
      return defer.promise();
    };
    
    getData().done(function() {
        var fetchData = App.request("element:entities:initialize", activityID);
        //do awesome stuff with fetchData here
    });
    

    However, if App.request() is also asynchronous, then it can't return data - it has to return a promise of data, and the code would be like this :

    function getData(activityID) {
      var defer = $.Deferred();
      require(["entities/element/element_collection"], function() {
        App.request("element:entities:initialize", activityID).done(defer.resolve);
      });
      return defer.promise();
    };
    
    getData(activityID).done(function(fetchData) {
        //do awesome stuff with fetchData here
    });
    

    or :

    function getData() {
      var defer = $.Deferred();
      require(["entities/element/element_collection"], defer.resolve);
      return defer.promise();
    };
    
    getData().done(function() {
        App.request("element:entities:initialize", activityID).done(function(fetchData) {
            //do awesome stuff with fetchData here
        });
    });
    

    If App.request() is asynchronous and neither returns a promise nor accepts a callback, then the person who wrote it needs to be spoken to. App.request() would need to be rewritten or you would need to find another utility to do the job.