24.3.14

wish: a tiny promise

The JavaScript Promises feature arrives in browsers natively around 2014. (See also: current support for promises)

Example: Fetch location, then weather data

I. With callbacks, not Promises

getWeather(function(weather){ 
  console.log(weather) });

function getWeather(then){
  getPosition(function(position){
    get('//api.openweathermap.org/data/2.5/weather?' 
            + 'lat=' + (0|position.coords.latitude)
            + '&lon=' + (0|position.coords.longitude), then); }); }

function getPosition(then){ 
  return navigator.geolocation.getCurrentPosition(then); }

function get(url, then){
  with (new XMLHttpRequest)
    onload = function(xhr){
      then(JSON.parse(xhr.target.response)); },
    open('GET', url),
    send(); }

II. With Promises

getPosition()
  .then(getWeather)
  .then(log);
  

function getPosition(){
    return new Promise(function(then){
        navigator.geolocation.getCurrentPosition(then); }); }

function getWeather(position){
    return new Promise(function(then){
        get('//api.openweathermap.org/data/2.5/weather?' 
            + 'lat=' + (0|position.coords.latitude)
            + '&lon=' + (0|position.coords.longitude)).then(then); }); }
            
function get(url, then){
  return new Promise(function(then){
    with (new XMLHttpRequest)
      onload = function(xhr){
        then(JSON.parse(xhr.target.response)); },
      open('GET', url),
      send(); }); };


function log(){
    console.log(arguments[0]) }

This does not look easier

Good one. It doesn't.
What matters is that the user flow is easier to read. While the implementation of the calls may be more complicated to understand and debug, these parts usually (especially with tests) do not see much change.
The difference may be subtle, but very important: Functional separation greatly improves maintainability. Once the functionality is available, it can be very easily reused by other flows without fuss. Conversely, the first example makes the code impossible or very difficult to reuse.

What do you think?

No comments: