Posted almost 5 years ago. Visible to the public.

An intro to Javascript promises

Promises are the new way™ to express "Do this, and once you're done, do that". In contrast to callbacks, promises are easily chainable. From the readme of Q, an early implementer of the pattern:

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 not a drop-in replacement for callbacks. Both have situations they shine in, with different implications and drawbacks. As a rule of thumb,

  • use callbacks to delegate control, e.g. in an event handler: "Hey, whenever a user clicks you, please run this code" (keyword "whenever")
  • use promises to make time consuming things async without writing async code, e.g. for animations: "Hey, once you're done with that animation, please run this code (keyword "once")

Promises are built into modern browsers and Microsoft Edge, there are polyfills for Internet Explorer. Usage:


Assume this piece of code returns a promise:

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".

const storePages = function(pages) {}; const notifyAboutError = function(errorMessage) {}; api.get('pages') .then(storePages, notifyAboutError .then(setupLinks);

In case a promise could not be fulfilled, the second parameter of then will be invoked as error handler.

Wrapping a callback in a promise

let p = new Promise(resolve, reject); let promise = p(() => asyncFunctionWithCallback(function(result) { if (result === 'success') { resolve(); } else { reject(); } })); promise.then(() => alert('Promise was resolved!'));

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

Legacy information


With jQuery, you would do it like this:

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:

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.

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Dominik Schöler
Last edit:
almost 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 short-lived cookies to improve usability.
Accept or learn more