Posted about 3 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:

Usage

Assume this piece of code returns a promise:

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

Copy
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

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.

Once an application no longer requires constant development, it needs periodic maintenance for stable and secure operation. makandra offers monthly maintenance contracts that let you focus on your business while we make sure the lights stay on.

Owner of this card:

Avatar
Dominik Schöler
Last edit:
13 days 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