When in doubt, return a promise. Plus promises are functors.

Prepare for future async data flow by wrapping primitives in promises.

I strongly suggest you return a promise from a method even at the early stages of prototyping if there is a chance the data will later be generated asynchronously. This adds only a tiny complexity overhead, but will make painless the switch in the future.

Example

Let us represent user information as an object. The user has several bits of information, all set in the constructor.

1
2
3
4
5
6
7
function User(username, profile) {
this.username = username;
this.profile = profile;
}
var foo = new User('foo', 'Foo is an excellent coder');
console.log(foo.username + ':', foo.profile);
// prints foo: Foo is an excellent coder

Notice that profile property might be a candidate to be fetched separately from the server. Thus to prepare for this change, instead of having a string primitive property, I wrap it in a promise, even if the value exists already

1
2
3
4
5
6
7
8
9
10
var q = require('q');
function User(username, profile) {
this.username = username;
this.profile = q(profile);
}
var foo = new User('foo', 'Foo is an excellent coder');
foo.profile.then(function (profile) {
console.log(foo.username + ':', profile);
});
// prints foo: Foo is an excellent coder

I do not like the syntax foo.profile.then - to me it looks a little weird. Instead I prefer promise-returning methods

1
2
3
4
5
6
7
8
9
10
11
var q = require('q');
function User(username, profile) {
this.username = username;
this.profile = function () {
return q(profile);
};
}
var foo = new User('foo', 'Foo is an excellent coder');
foo.profile().then(function (profile) {
console.log(foo.username + ':', profile);
});

A transition to fetching the profile from the server now is trivial

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var q = require('q');
// mock ajax using Q
var $ = {
get: function (url) {
return q('Foo is an excellent coder');
}
};
function User(username) {
this.username = username;
}
User.prototype.profile = function () {
return $.get('/profile/' + this.username);
};
// nothing needs to change in client API
var foo = new User('foo');
foo.profile().then(function (profile) {
console.log(foo.username + ':', profile);
});

Promises are functors

The above example shows how I prepare for asyncronous data flow. The primitive values wrapped like this have another name: functors. Instead of using the primitive value I wrap it in an object that only has to provide a method to run a function on the primitive. In the case of promises, this method is .then. It takes a single callback function, passing the primitive value. After the function returns, a new promise is returned that wraps around the value returned from the callback function.

1
2
function double(x) { return x + x; }
q('foo').then(double); // returns new promise that wraps 'foofoo'

With functors, we do not use the underlying primitive value itself, as you saw from the example. Even pure printing now requires passing a callback function

1
2
3
4
function double(x) { return x + x; }
q('foo').then(double).then(function (result) {
console.log(result);
});

One final detail: every returned value is wrapped in promise, thus the above example finishes with a promise wrapping an undefined value.

1
2
3
q('foo').then(function (result) {
console.log(result); // nothing is returned => undefined
}); // returns new promise that wraps an undefined

In general, using functors instead of primitives makes your software more flexible. You can find more examples of functors in these 3 blog posts