An introduction to Promises

Today we want to look at Promises. This handy feature is natively available in JavaScript since ES2015.

But what are Promises? How do you use it?

Let’s see how it works!

The callback hell

Everyone familiar with JavaScript came across the so called “callbacks”. It’s very hard for some beginners to pick up the term because this style of programming is not what one may be used to when starting out with traditional programming languages such as C or Java.

A callback is basically a function you can pass to another function which is evaluated once the parent function has done it’s computations (it “calls back”).

Here’s a simple example which show just that:

// parent function
doSomething('path/to/a/file.txt', function() {
console.log('done');
});

In this case an anonymous function is passed as the second parameter to the doSomething function. “done” is printed on the console once the function is finished with it’s computation.

You came across this pattern frequently as a Meteor developer e.g. when you call a remote method:

// calling a method
Meteor.call('addUser', function (error) {
if (error) {
console.log(error);
} else {
console.log('success');
}
});

But callbacks are more than that. You can nest them easily and create a callback chain which makes it easy to develop powerful applications. But soon you’ll run into the so called “callback hell”

// callbacks
function getUserInformation(id, callback) {
openDatabaseConnection(function (database) {
getUsers(db, 'users', function (columns) {
findUser(columns, { 'id': id }, function (result) {
result.find(function (user) {
callback (user);
});
});
});
});
}

This code is pretty hard to read and reason about.

Promises to the rescue

This problem started the implementation of alternative ways to deal with callbacks. One solution which was developed to solve this “mess” is called “Promises”.

Promises are objects that “promise” to return something in the future (which is not yet defined). A promise can return something positive (“resolve”) or negative (“reject”).

Sounds hard to understand? It’s not, believe me.

Let’s transform the code above with multiple callbacks into a promise based solution and see what it looks like:

// promises
function getUserInformation(id) {
return openDatabaseConnection(database)
.then(getUsers)
.then(findUser({ 'id': id }))
.then(function (user) {
return resolve(user);
});
}

This code works the exact same way as the callback based solution above and it’s pretty easy to read isn’t it?

What has Meteor to do with it?

Back in the days when ES2015 was not widely available (thanks to transpires such as babel) promise based solutions were available as libraries (such as e.g. Bluebird promises). However it was not that easy / natural to implement those promises into a Meteor application.

The switch to embrace ES2015 as the standard JavaScript version for Meteor in 1.2 introduced a new range of language specific features which are available to the Meteor system.

Now you are able to use a natively available promise based solution in Meteor without the extra effort to add and configure a special promise library.

Soon enough this will be the standard to write asynchronous code without the hassle of callbacks.

Additional resources