Promise pattern

I said earlier that JavaScript is single threaded. This is not entirely accurate. There is a single event loop in JavaScript. Blocking this event loop with a long running process is considered to be bad form. Nothing else can happen while your greedy algorithm is taking up all the CPU cycles.

When you launch an asynchronous function in JavaScript, such as fetching data from a remote server, then much of this activity happens in a different thread. The success or failure handler functions are executed in the main event thread. This is part of the reason that success handlers are written as functions: it allows them to be easily passed back and forth between contexts.

Thus there are activities which truly do happen in an asynchronous, parallel fashion. When the async method has completed then the result is passed into the handler we provided and the handler is put into the event queue to be picked up next time the event loop repeats. Typically, the event loop runs many hundreds or thousands of times a second, depending on how much work there is to do on each iteration.

Syntactically, we write the message handlers as functions and hook them up:

var xmlhttp = new XMLHttpRequest(); 
xmlhttp.onreadystatechange = function() { 
  if (xmlhttp.readyState === 4){ 
    alert(xmlhttp.readyState); 
  }
;};

This is reasonable if the situation is simple. However, if you would like to perform some additional asynchronous actions with the results of the callback then you end up with nested callbacks. If you need to add error handling that too is done using callbacks. The complexity of waiting for multiple callbacks to return and orchestrating your response rises quickly.

The promise pattern provides some syntactic help to clean up the asynchronous difficulties. If we take a common asynchronous operation such as retrieving data over XMLHttp Request using jQuery, then the code takes both an error and a success function. It might look something like the following:

$.ajax("/some/url",
{ success: function(data, status){},
  error: function(jqXHR, status){}
});

Using a promise instead would transform the code to look more like the following:

$.ajax("/some/url").then(successFunction, errorFunction);

In this case the $.ajax method returns a promise object that contains a value and a state. The value is populated when the async call completes. The status provides some information about the current state of the request: has it completed, was it successful?

The promise also has a number of functions called on it. The then() function takes a success and an error function and it returns an additional promise. Should the success function run synchronously, then the promise returns as already fulfilled. Otherwise it remains in a working state, known as pending, until the asynchronous success has fired.

In my mind, the method in which jQuery implements promises is not ideal. Their error handing doesn't properly distinguish between a promise that has failed to be fulfilled and a promise that has failed but has been handled. This renders jQuery promises incompatible with the general idea of promises. For instance, it is not possible to do the following:

$.ajax("/some/url").then(
  function(data, status){},
  function(jqXHR, status){
    //handle the error here and return a new promise
  }
).then(/*continue*/);

Even though the error has been handed and a new promise returned, processing will discontinue. It would be much better if the function could be written as the following:

$.ajax("/some/url").then(function(data, status){})
.catch(function(jqXHR, status){
  //handle the error here and return a new promise
})
.then(/*continue*/);

There has been much discussion about the implementation of promises in jQuery and other libraries. As a result of this discussion the current proposed promise specification is different from jQuery's promises and is incompatible. Promises/A+ are the certification that is met by numerous promise libraries such as when.js and Q. It also forms the foundation of the promises specification that came with ECMAScript-2015.

Promises provide a bridge between synchronous and asynchronous functions, in effect turning the asynchronous functions into something that can be manipulated as if it were synchronous.

If promise sounds a lot like the lazy evaluation pattern we saw some chapters ago then you're exactly correct. Promises are constructed using lazy evaluation, the actions called on them are queued inside the object rather than being evaluated at once. This is a wonderful application of a functional pattern and even enables scenarios like the following:

when(function(){return 2+2;})
.delay(1000)
.then(function(promise){ console.log(promise());})

Promises greatly simplify asynchronous programming in JavaScript and should certainly be considered for any project that is heavily asynchronous in nature.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset