Posted over 2 years ago. Visible to the public.

How to use Javascript promises

Promises are the new way™ to express "Do this, and once you're done, do that". In contrast to callbacks, promises are chainable.

From the readme of Q:

The callback approach is called an “inversion of control”. A function that accepts a callback instead of a return value is saying, “Don’t call me, I’ll call you.”. Promises un-invert the inversion, cleanly separating the input arguments from control flow arguments. This simplifies the use and creation of APIs, particularly variadic, REST and spread arguments.

Note that promises are no drop-in replacement for callbacks. Both have situations they shine in, with different implications and drawbacks. As a rule of thumb,

  • use callbacks when you need to delegate control, e.g. in an event handler: "Hey, whenever a user clicks you, please run this code" (keyword whenever)
  • use promises when you want to make time consuming things (like HTTP requests or animations) async, without having to write async code (keyword when you're done)

Using promises

Many libraries return promises e.g. for async HTML requests. It may look like this:

Copy
api.get('pages') # => Promise

You may now chain function calls to the promise using .then(), without needing to wait for the HTML request to actually return. The promise will collect all functions passed to then() and invoke them once the original promise "resolves".

Copy
storePages = -> ... setupLinks = -> ... api.get('pages').then(storePages).then(setupLinks).then(...)

In case a promise could not be fulfilled, a second parameter will be invoked as error handler:

Copy
storePages = (pages) -> # Store them handleError = (error) -> # Notify user api.get('pages').then(storePages, handleError)

This is just the most basic usage. Read more about promises in the readme of Q and the doc page of $q.

Building promises yourself

When you are building something with a lengthy execution time, you might want to make it async and offer its users promises instead.

You will encounter various implementations of promises. They all do the same thing in the end, but the way you construct a new promise differs.

jQuery

With jQuery, you would do it like this:

Copy
deferred = $.Deferred() callAsyncFunction (result) -> if result == 'success' deferred.resolve() else deferred.reject() promise = deferred.promise() promise.then(-> alert('Promise was resolved!'))

In jQuery, the difference between a "Deferred" and a "Promise" is that a deferred has resolve and reject methods in addition to then. A Promise only has then. When you hand back your promise to other code, it's considered good practice to only give back a Promise, never a Deferred.

AngularJS 1.x

In Angular's $q promise library, you would do it like this:

Copy
promise = $q (resolve, reject) -> callAsyncFunction (result) -> if result == 'success' resolve() else reject() promise.then(-> alert('Promise was resolved!'))

$q calls its argument function with two functions resolve and reject. These are used to propagate the outcome of the promise. Call resolve() to fulfill the promise, or reject() if something went wrong.

Inside the argument function you can do whatever you like. Just make sure to call the respective function when you're done.

Native promises

Promises are built into modern browsers and Microsoft Edge, but Internet Explorer does not support it in either versions.

Usage is similar to Angular's $q:

Copy
promise = new Promise(resolve, reject) -> callAsyncFunction (result) -> if result == 'success' resolve() else reject() promise.then(-> alert('Promise was resolved!'))

Exercises

You can experiment with callbacks vs. promises in our curriculum lesson.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Avatar
Dominik Schöler
Last edit:
about 2 years ago
by Dominik Schöler
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more