Lightweight promises (or deferred, or futures) in Javascript
Promises are a programming pattern to deal with asynchronous tasks. Instead of passing a callback to the asynchronous function, you attach callbacks to the value it returns.
Download library »
View source »
A lot of Javascript programming involves asynchronous programming. The usual way to deal with this is to pass a callback function that should be invoked once the asynchronous task has been done.
/* Call the _get() function with a callback. */ _get('/posts/1234', function(data, error) { if (error) { alert("error"); return; } do_something(data); }
In the code above, _get()
does not return a value, instead it takes a function as a parameter, to which it will pass the value when it is available.
Promises are a programming pattern where asynchronous functions do return something: a Promise object. A Promise represents a future value, that will be available later. In my lightweight implementation, a Promise has two methods:
.then(function(value, error))
Attach a function that will be invoked when the value is available.
.done(value, error)
Set the value.
(The error
parameter allows to propagate an error code. You can leave it undefined if everything went OK.)
Example
A get()
function that returns a promise would be used like this:
/* get() returns a Promise. */ var p = get('/posts/1234'); /* * Call then() to attach a callback to the promise. */ p.then(function(data, error) { if (error) { alert("error"); return; } do_something(data); });
The implementation of that promise-style get()
function — using the callback-style _get()
function — is the following :
function get(url) { /* Create a Promise. */ var p = new promise.Promise(); /* Make an asynchronous call. */ _get('/posts/1234', function(data, error) { /* * when the asynchronous task is done, * call done() on the promise. */ p.done(data, error); }); /* Return the promise immediately. */ return p; }
Advantages
Clearer code: function signatures are not polluted with a callback parameter.
Multiple callbacks: you can attach several callbacks by calling then()
multiple times, no need to build a huge callback.
Ability to attach a callback later: you don’t have to pass a callback when the function is called, you can attach one later.
Ability to join or sequentialize asynchronous code: this is provided easily by utility functions that I will present in the next post.
Download library »
View source »