One of the questions I like to ask when doing a job interview, is to ask the candidate, "Is JavaScript synchronous, or asynchronous?" For the average developer, this should be a piece of cake, however it is remarkable how many people mess it up.

When making an ajax call to the website, you are most likely going to use asynchronous JavaScript, i.e. the execution of code does not follow the order of the code as it is written. If you write:

console.log('A');
console.log('B'); 

You will always get "AB". If you are making an AJAX call, you will probably get 'BA', depending on how fast the AJAX call returns:

$.get("/api/users", function(data){
  console.log('A');
});
console.log('B'); 

What is happening here is a callback function, the second parameter in jQuery's GET function is a callback function and this could be specified inline (as above) or by reference.

What is more interesting, is that you are able to define your own functions which accept and execute callback functions when an event happens. This can be useful to make events happen in sequence.

function getUsers(callback) {
  $.get("http://jsonplaceholder.typicode.com/users", function(data){
    data.forEach(function(user){
      $("#myList ul").append('<li>' + user.name + '</li>');
    });
    callback();
  })
}

getUsers(function(){
  $("#myList ul").append("<li>...DONE</li>");
});

So what's going on here? First of all, we are defining a function getUsers, which accepts a function as a parameter. We then call the jsonplaceholder RESTful API using jQuery.get, and upon success, we will iterate through the data and append them to the <ul> element within the #myList. Once that is completed, we will fire the callback parameter (which we previously stated was a function) and this will begin executing. This will finally write "...DONE" below the list. Note that DONE will always follow the list of users, hence we have created a sequence.

http://codepen.io/anon/pen/peACI

That's fine, but we could improve it slightly so that the functionality in the case of a successful return, will also be abstracted from the getUsers. We always want to avoid coupling between functions that are doing different things, therefore getUsers only gets the users and printUsers will print the users.

function getUsers(callback) {
  $.get("http://jsonplaceholder.typicode.com/users", function(data){
    callback(data);
  })
}

function printUsers(data){
  data.forEach(function(user){
    $("#myList ul").append('<li>' + user.name + '</li>');
  });
  $("#myList ul").append("<li>...DONE</li>");
}

getUsers(printUsers);

http://codepen.io/anon/pen/gmbEG

Taking a look at the above code, the only significant differences are that we are no longer specifying the function inline and we are passing data to the callback function, which in turn parses that data and prints it in a list. So far so good, everything works and the code is decoupled; so why do we need promises? As your number of callbacks increases, it is likely that your code will no longer remain neatly structured as your callbacks will be nested inside eachother, leading to messy code.

Let's refactor the above code to use jQuery promises (note that there are different implementations of promises - Angular, jQuery...etc; but they all follow the same pattern):

function getUsers() {
  var deferred = $.Deferred();
  $.get("http://jsonplaceholder.typicode.com/users", function(data){ 
    deferred.resolve(data);
  });

  return deferred.promise();
}

function printUsers(data){
  data.forEach(function(user){
    $("#myList ul").append('<li>' + user.name + '</li>');
  });
  $("#myList ul").append("<li>...DONE</li>");
}

$.when(getUsers()).then(function(data){
  printUsers(data);
});

 Let's take a look at the getUsers() function. Instead of accepting the callback function as a parameter, it now initializes an instance of $.Deferred(). The Deferred object controls the state of a promise, i.e. is it resolved, is it pending...etc. We then do our ordinary AJAX request, and upon completion, we run deferred.resolve, passing the data as a parameter. Finally we return the promise of the deferred instance. The reason to return the promise is to prevent the deferred from being resolved outside of this function. Further down, we call our getUsers function and follow this with .then. This is because getUsers now returns a Deferred obejct and the function parameter in .then is only executed once the deferred is resolved.

http://codepen.io/anon/pen/sejbf

Ultimately, this does exactly the same thing as the previous example, however we can now extend this in a more elegant way. If we have multiple promises, we could call jQuery's apply over them and proceed only when ALL have been resolved.

 

function getUsers() { 
  var deferred = $.Deferred();
  $.get("http://jsonplaceholder.typicode.com/users", function(data){   
    deferred.resolve(data);
  });
 
  return deferred.promise();
}

function getTodos() {
  var deferred = $.Deferred();
  $.get("http://jsonplaceholder.typicode.com/todos", function(data){   
    deferred.resolve(data);
  });
 
  return deferred.promise();
}

function printUsers(data){ 
  data.forEach(function(user){
    $("#myList ul").append('<li>' + user.name + '</li>');   
  });    
}

$.when.apply($, [getUsers(), getTodos()]).then(function(users, todos){ 
  printUsers(users);
});

Ultimately, this will allow us to set up conditions in our code and not worry about which promises have to be completed and which not. Check out the awesome CodePen below:

http://codepen.io/anon/pen/icseq

UPDATE: user "attilakling" correctly pointed out that the jQuery AJAX request already returns a promise, so it would be possible to refactor this slightly to return $.get("...") immediately or use $.get("...").then():

http://codepen.io/jim-y/pen/JGlId

Apart from this, promises also include additional functionality, such as .notify, .reject and .done; which execute at different times. I have included a final CodePen below illustrating the different scenarios.

Thanks for reading and hope to see you using promises.