Fez Vrasta
Fez Vrasta

Reputation: 14835

Add .done() callback to custom function

I've these functions included in a small class:

var Ajax = {
  // Send new entry data to database
  endNewEntry: function (json) {
    $.post("/controllers/insertEntry.ajax.php", {"json": json});
  },
  loadView: function (view, target, extra) {
    var input = $.extend({}, {"view": "../" + view}, extra) || {"view": "../" + view};

    $.get("/controllers/loadView.ajax.php", input, function (data) {
      $(target).replaceWith(data);
    });
  }
};

As you can see, both functions use jQuery $.ajax to perform requests to my server and replace part of my document with the response.

Now I'd like to add a feature to these functions to let me call another function (callback) when the post request is finished.

I'd like this syntax:

Ajax.loadView(view, target, extra).done( function() { something; });

The only way I know, instead, is to add another parameter to loadView where my callback function is defined, but I would like to have the .done() function.

How can I do?

Upvotes: 2

Views: 1862

Answers (2)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276306

done is a part of a promise API.

Promises are an abstraction over flow control that lets you write asynchronous code in a "more synchronous" way.

A promise object has a .then method that allows you to chain operations to it, and each operation is guaranteed to terminate only when the previous one has finished.

myAjax().then(function(result){
    // do something with result, myAjax done here
    return otherAjax();
}).then(function(otherResult){
    // otherAjax done here, this only gets called after the above code handling myAjax is done
});

Promise implementations, at least some of them, include a .done method that is like .then with the difference that it logs errors to the console rather than allow you to handle them within a promise chain (another awesome thing promises can do).

You can simply return the promise in your case:

var Ajax = {
  // Send new entry data to database
  endNewEntry: function (json) {
    return $.post("/controllers/insertEntry.ajax.php", {"json": json});
  },
  loadView: function (view, target, extra) {
    var input = $.extend({}, {"view": "../" + view}, extra) || {"view": "../" + view};

    return $.get("/controllers/loadView.ajax.php", input, function (data) {
      $(target).replaceWith(data);
    });
  }
};

Which would let you do:

Ajax.loadView().done(function(data){
    //do something with the result, in variable data here.
});

You can of course chain things to it like illustrated above in order to perform more than one asynchronous operation. jQuery also provides $.when for waiting for multiple promises.

It's worth mentioning that there are much better, faster and more able promise implementations out there.

Upvotes: 4

Johan
Johan

Reputation: 35194

Since $.get returns a promise (assuming you are using jQuery >= 1.7), just return in and you get access to the properties that you're after:

return $.get("/controllers/loadView.ajax.php", input, function (data) {
  $(target).replaceWith(data);
});

And I would personally handle $(target).replaceWith(data); in the done() callback as well, to avoid confusion.

Upvotes: 2

Related Questions