JavaScript Promises

Patrick Beer - @pabera

1. Why JavaScript Promises?

Promises are a different way of handling asynchronous functionality and requests without using simple callback functions.

Some problems with the callback function approach
  • Input and output are decoupled, the output callback needs to be passed as an input
  • Creating parallel operations is hard
  • When it comes to debugging, the stack trace does not provide all the information anymore we need

What is a Promise?

A promise represents the value that is the result of an asynchronous operation (Examples: general data/content, thrown errors).

Specification - Promises/A+ spec

2. Basic Usage

Example 1

var promise = get('http://amazon.com');

Example 2

promise.done(function(evt) {
  console.log(evt);
});

.done() can be called as many times you want. It will always return the same once it has been called.

Except a second function to handle errors

Promise.done(function(content) {}, function(error) {});

3. Conversion

Chaining promises with .then().

Example 3

function getContent(url) {
  return get(url)
    .then(function (content) {
      return content;
    });
}

getContent('http://amazon.com').done(function (result) {
  console.log(result)
})

.then() also excepts an error argument

.then( event, error )

Example 4

function getContent(url) {
  return get(url)
    .then(function (result) {
      return result;
    }, function (error) {
      if (canRetry(error)) {
        return getContent(url);
      }
      else {
        throw error;
      }
    });
}

getContent('http://www.amazon.com').done(function (content) {
  console.log(content);
});

Use multiple .then() (Example 5)

var promise = get('http://www.amazon.com')
  .then(function (url) {
    return get(url);
  })
  .then(function (result) {
    return result;
  })
promise.done(function (final) {
  console.log(final);
});

Mix it! (Example 6)

var a = get('http://www.amazon.com');
var e = get('http://www.ebay.com');
var both = Promise.all([a, e]);
both.done(function (result) {
  var a = result[0];
  var e = result[1];
  console.log({
    'amazon': a,
    'ebay': e
  });
});

Useful if you need to run a lot of operations in parallel
Best example: image file preloader

Serialize it (Example 7)

get('http://www.amazon.com').then(function (result) {
  console.log('amazon');
  console.dir(result);
  return get('http://www.ebay.com')
}).done(function (result) {
  console.log('ebay');
  console.dir(result);
});

3. Implementations

Node

npm install promise

Usage

var Promise = require('promise')

There are some browser implementations as well

Some browser implementations

4. Some theory

Promise States
fulfilledThe promise related action has successfully been terminated
succeeded rejectedgoto fail;
failed pendingHasn't fulfilled or rejected yet
yet settledHas fulfilled or rejected

5. Practical Example

Standard asynchronous callback paradigm

Simple Example

object.save({ key: value }, {
  success: function(object) {
    // the object was saved.
  },
  error: function(object, error) {
    // saving the object failed.
  }
});

We can do it like this with promises.

object.save({ key: value }).then(
  function(object) {
    // the object was saved.
  },
  function(error) {
    // saving the object failed.
  });
Why is that better now?

Advanced Example

Callbacks

Parse.User.logIn("user", "pass", {
  success: function(user) {
    query.find({
      success: function(results) {
        results[0].save({ key: value }, {
          success: function(result) {
            // the object was saved.
          }
        });
      }
    });
  }
});

Promises

Parse.User.logIn("user", "pass").then(function(user) {
  return query.find();
}).then(function(results) {
  return results[0].save({ key: value });
}).then(function(result) {
  // the object was saved.
});

Error Handling

Parse.User.logIn("user", "pass").then(function(user) {
  return query.find();
}).then(function(results) {
  return results[0].save({ key: value });
}).then(function(result) {
  // the object was saved.
}, function(error) {
  // there was some error.
});

Basic Implementation of a Promise

Create the promise

var promise = new Promise(function(res, rej) {
  // Code something great

  if (true) {
    areWeDone(true);
  }
  else {
    areWeDone(false);
  }
});

Use it

promise.then(function(result) {
  console.log(result); // "areWeDone(true)"
}, function(err) {
  console.log(err); // Error: "areWeDone(false)"
});

Sources

  • https://github.com/then/promise
  • http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=cs
  • http://blog.parse.com/2013/01/29/whats-so-great-about-javascript-promises/
  • http://www.promisejs.org/intro/
  • http://mattgreer.org/articles/promises-in-wicked-detail/