Question

---EDITED---due to my ignorance, this is actually the same as alllll the other AJAX-type questions out there...need to get into the right mindset. Leaving it here for posterity's sake and maybe help others take a second look at callbacks before posting.

So I would like to say up front that I think this is not the standard "how do I return a value from an ajax call" issue where people aren't waiting for the async call to finish. I think this is a variable scope misunderstanding with Javascript module patterns, so any guidance would be appreciated.

I am following this SO post on constructing my ajax call, so I am using deferred objects to crunch my data after the call finishes. And also several tutorials on the Javascript module pattern, like this and this. It seems fairly straightforward to return values from within a private module inside my outer module--however, I always get myObj.roots() as undefined. Even though it is defined as an array of X values when I check with breakpoints. What simple thing am I missing--any hints? Thanks! Sorry for a simple question, I'm entirely new to JS module patterns and trying to build my own library...

My JS code:

var myObj = (function(window,document,$,undefined){

  var _baseUri = 'http://example.com/',
      _serviceUri = 'services/',
      _bankId = '1234',
      _myUri = _baseUri + _serviceUri + 'objectivebanks/' + _bankId,
      _roots = [];

  function myAjax(requestURL) {
    return $.ajax({
      type: 'GET',
      url: requestURL,
      dataType: 'json',
      async: true
    });
  }

  var getRoots = function() {
    var _url = _myUri + '/objectives/roots';
    _roots = [];
    myAjax(_url).done(function(data) {
      $.each(data, function(index, nugget) {
        _roots.push(nugget);
      });
      return _roots;
    }).fail(function(xhr, textStatus, thrownError) {
      console.log(thrownError.message);
    });
  }

  return {
    roots: getRoots
  };
})(this,document,jQuery);

My error (from Chrome's developer tools' console):

myObj.roots()
undefined
Was it helpful?

Solution

Your "getRoots" function does not return anything. Using the $.ajax(successCallback) or $.ajax.done() patter is the same thing. You are not deferring anything. There is no way you can do this without callbacks, events or promises. Callbacks and events are basically the same, only the latter allow better architectural decoupling (highly debatable fact). Promises mean that you can write var x = getRoots() and x will be undefined until the browser gets back a response from the server. Your application has to account for this. So either you start coding with the async pattern in mind (callbacks, events) or design applications that handle null/undefined values gracefully.

Using callbacks:

function getStuff(callback) {
    $.ajax(...).done(function(data) {
        // maybe process data?
        callback(data);
    });
}

getStuff(function(data) {
    // this is where I can use data
});

This way you can write your getStuff methods in a separate module, say "DataService" so MVC logic is not polluted.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top