Search code examples
javascriptajaxcallbackchaining

Ajax callback in chain


I'm having a navigation bar on my site, and it's being built in some chain:

// in Init method
nav
    .hideContainer()
    .fetchData()
    .buildHTML()
    .eventify()
    .showContainer();

It's OK, and works fine for me. But in fetchData method I use local data to load ( inline json). But now, I need to get remote data (from an ajax calling). Can I make it without changing Init method?

I had an attempt to do this with an synchronous ajax call:

// in fetchData() method
var data;
$.ajax ({
     async: false,
     url : '/some/url/',
     success : function(res) {
         data = res;
     }
});
return data;

But I know, that it's slow - it's blocking the browser while it's loading.

I know, that I can modify my Init method, like in a such way:

nav
    .hideContainer()
    .fetchData(function(){
        nav.buildHTML().eventify().showContainer()

 });

But, I'd like not to modify Init method, can I do this?

P.S. I think I should go in direction of Deffered object. Am I right?


Solution

  • You cannot have $.ajax working asynchronously and at the same time expect .fetchData() to return with your data.

    You are right that setting async: false is bad and changing the init() is a better alternative even when you lose elegant chaining.

    You can change your code like this:

    function fetchData() {
      // ...
      return $.ajax ({
        url : '/some/url/',
        success : function(res) {
         data = res;
        }
      });
    }
    
    function init() {
      // ...
      nav
        .hideContainer()
        .fetchData()
        .done(function() {
          nav
            .buildHTML()
            .eventify()
            .showContainer(); });
    

    You don't have to introduce callbacks into fetchData() function, because you can return deferred object returned by ajax() and then call done() on it - see documentation.

    See also fail() and then() if you want to handle errors.