Edit in JSFiddle

// promise allows us to write code for situations which say "when all of these things have happened do this one more thing". Promise is an object that is initially in a pending state and then can go to resolved(success) or rejected(failure) state. Once a promise reaches resolved or rejected state, it will remain in that state forever and its callbacks will not fire again.
// a deferred object is like a promise with methods that allow its owner to resolve or reject. A promise object doesnt have methods that allow its owner to resolve or reject. Hence promise is a deferred object with resolve() and reject() methods missing. By calling deferred.promise() we can get hold of the promise object.
// jquery's ajax methods do the same. They return a promise object so that the caller can not resolve or reject it. It would be odd if the caller was allowed to determine whether the ajax was successful or failed.
// once we have a promise object we can attach as many callbacks as we like using done(), fail() and always() methods
var divLoading = $("#divLoading");
divLoading.hide();
var container = $("#container");
var successFunc = function() {
    container.append("both calls succeeded");
    divLoading.hide();
};
var failureFunc = function() {
    container.append("one or both calls failed");
    divLoading.hide();
};

$("#btnLoad").click(function() {
    divLoading.show();
    // execute a function after 2 ajax requests are successful or failed
    // here we have 2 promises. The successFunc is called if both promises are succesful. failureFunc is called if either one or both promises fail.
    // then is providing the success and failure callbacks
    $.when($.ajax("/somerequest"), $.ajax("/someotherrequest")).then(successFunc, failureFunc);

});
// this example shows how we can chain multiple success and failure functions. In current ajax method we can only specify one success and failure.
var container1 = $("#container1");
$("#btnLoad1").click(function() {
    $.ajax("test.html").done(function(data) {
        container1.append('ajax request was successful 1' + "<br/>");
    }).done(function(data) {
        container1.append('ajax request was successful 2' + "<br/>");
    }).fail(function(data) {
        container1.append('ajax request failed 1' + "<br/>");
    }).fail(function(data) {
        container1.append('ajax request failed 2' + "<br/>");
    });
});
//pipe demo
$("#btnPipe").click(function() {
    var container2 = $("#container2");
    var def1 = $.Deferred();
    container2.append(def1.state() + "<br/>");
    def1.resolve();
    container2.append(def1.state() + "<br/>");
    def1 = $.Deferred();
    container2.append(def1.state() + "<br/>");
    def1.reject();
    container2.append(def1.state() + "<br/>");
    def1 = $.Deferred();
    container2.append(def1.state() + "<br/>");
    var def2 = def1.pipe();
    // pipe returns a new promise that allows us to filter or process the values of a deferred through another function
    container2.append("def2: " + def2.state() + "<br/>");
    def2.done(function(data){
        container2.append('successful. processing number: ' + data + "<br/>");
    });
    def2.fail(function(data) {
        container2.append('failed. processing number: ' + data + "<br/>");
    });
    var randomnumber=Math.floor(Math.random()*11);
    console.log(randomnumber);
    def1.resolve(randomnumber); //try running first with this statement and later comment it out and uncomment the below statement
    //def1.reject(randomnumber);
    container2.append("def2: " + def2.state() + "<br/>");
});


<div id="divLoading">Loading...</div>
<input id="btnLoad" type="button" value="Make some call"/>
<div id="container"></div>
<hr/>
<input id="btnLoad1" type="button" value="Make another call"/>
<div id="container1"></div>
<hr/>
<input id="btnPipe" type="button" value="Pipe Demo"/>
<div id="container2"></div>
<hr/>