JavaScript Interview Prep: “What is a Promise?”

What is a promise graphic

The most common answers I hear are along the lines of

It is a thenable

Or even worse

It’s a promise for something

But we can do much better than that. At its essence a promise is an object encapsulating function that has yet to complete execution. Objects typically adhere to a common interface and in the case of promises these objects have the method then (thus the term thenable). Promises were intended to clean up the callback mess you get in in continuation passing style. So here is a definition of Promise I plan on using the next time I am asked:

A promise is an object encapsualting a function, in any phase of execution, that implements the promise interface, exposing a method then. This method is used to provide the result of the encapsulated function when it is available to all points in your application that need it. Promises are intended to provide cleaner code than continuation passing style and offer a nice way to compose asynchronous functions.

Before generalizing promises I wanted to expand my understanding by writing a function to adapt a nodeback style function fs.readFile to one that returns a promise to the files contents. The goal is to convert this:

to something that looks like this:

The first step in recreating a naive implementation is defining the function (asPromise) that takes a nodeback style callback (traditionalNodeBack) and converts it to a function which returns the promise. The scaffolding is pretty simple:

The asPromise function is defined in curried style to first take a traditional nodeback (traditionalNodeBack) style function and return a function that will be all of the arguments necessary (args) to invoke that function minus the node style callback. We then need to return an object (a Promise object) that has the methods for collecting the callbacks for the then and catch functionality.

The trick is with the Promise object returning a recursive reference in the then and catch methods to allow for chaining those methods. The remainder of this naive implementation is invoking the intended function and triggering the promise methods. This can be accomplished by defining an internal node style callback and appending that to the list of arguments and invoking our intended function.

There is some ES6 trickery with the call method and the use of the spread operator, but this could be replaced with pushing the resolveOrReject onto the args and leveraging apply instead.

This solution lacks robustness. It doesn’t support chaining of thens, promise for values or generalized deferrable functions. However promises come native in ES6 and prior to that there were already great solutions like Kris Kowal’s Q. The readme on that library is still a definitive source in understanding the implementation concerns of promises.

I haven’t sat as a candidate in a JavaScript interview for quite some time. However this question had surfaced on a number of occasions and we often dovetailed on how they might be implemented. For a detailed discussion of deferrables look at Mr Kowal’s readme. However the essential bits are

  1. Return an object to collect thens and catchers
  2. Invoke the function/code in question
  3. When it resolves pass the results to the thens and catchers you collected

The details on single resolvability, encapsulating multiple forms of deferred code, chaining of thens (of results into promises themselves) are the finer details that matter less as part of a whiteboard exercise.

A 25 year software industry veteran with a passion for functional programming, architecture, mentoring / team development, xp/agile and doing the right thing.

A 25 year software industry veteran with a passion for functional programming, architecture, mentoring / team development, xp/agile and doing the right thing.