链中的Ajax回调

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?

Do something like this in your fetch Method

$.ajax ({
     url : '/some/url/',
     success : buildHTML
});

Then, when the data comes in, it will call buildHTML()

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.