JavaScript is a widely used programming language that makes extensive use of asynchronous computation, particularly in the form of asynchronous callbacks. These callbacks are used in modern JavaScript applications to handle tasks, from GUI events to network messages, in a non-blocking fashion. Asynchronous callbacks present developers with two challenges. First, JavaScript’s try/catch error-handling mechanism is not sufficient for proper error handling in asynchronous contexts. In response, the JavaScript community has come to rely on the error-first protocol, an informal programming idiom that is not enforced or checked by the JavaScript runtime. Second, JavaScript callbacks are frequently nested, making them difficult to handle (also known as callback hell). Fortunately, a recent language extension called promises provides an alternative to asynchronous callbacks. The adoption of promises, however, has been slow as refactoring existing code to use promises is a complex task.

In this paper we present a set of program analysis techniques to detect instances of asynchronous callbacks and to refactor such callbacks, including callbacks with the error-first protocol, into promises. We implement our techniques in a tool called PromisesLand. We perform a manual analysis of four JavaScript applications to evaluate the tool’s precision and recall, which are, on average, 100% and 83%, respectively. We evaluate PromisesLand on 21 large JavaScript applications, and find that PromisesLand (1) correctly refactors callbacks to promises, (2) outperforms a recent related refactoring technique, and (3) runs in under three seconds on all of our evaluation targets.


Full dataset can be downloaded from here:

Download Data

Source code used to analyze the subject systems can be accessed here:

Source Code

Reasons motivating developers to use Promises over callbacks:

Exploratory study results

Subject Systems

This set of subject systems consist of 21 Node.js modules and is expected to be representative of a majority of commonly used JavaScript modules.

# Project Name Release URL
1 heroku-bouncer 4.0.1 https://www.npmjs.com/package/heroku-bouncer
2 redis-key-overview 0.0.3 https://www.npmjs.com/package/redis-key-overview
3 slack-integrator 0.0.6 https://www.npmjs.com/package/slack-integrator
4 timbits 0.7.3 https://www.npmjs.com/package/timbits
5 tingo-rest 1.0.1 https://www.npmjs.com/package/tingo-rest
6 brokowski 0.1.8 https://www.npmjs.com/package/brokowski
7 express-user-couchdb 0.3.5 https://www.npmjs.com/package/express-user-couchdb
8 express-device 0.3.11 https://www.npmjs.com/package/express-device
9 flair-doc 0.1.0 https://www.npmjs.com/package/flair-doc
10 http-test-servers 0.0.12 https://www.npmjs.com/package/http-test-servers
11 jellyjs-plugin-httpserver 0.0.8 https://www.npmjs.com/package/jellyjs-plugin-httpserver
12 gifsockets-server 0.38.1 https://www.npmjs.com/package/gifsockets-server
13 moonridge 0.6.9 https://www.npmjs.com/package/moonridge
14 moby 1.1.1 https://www.npmjs.com/package/moby
15 monami 0.0.21 https://www.npmjs.com/package/monami
16 oauth-express 0.0.1 https://www.npmjs.com/package/oauth-express
17 public-server 2.0.1 https://www.npmjs.com/package/public-server
18 scrapit 0.0.4 https://www.npmjs.com/package/scrapit
19 express-endpoint 1.2.11 https://www.npmjs.com/package/express-endpoint
20 sonea 0.0.3 https://www.npmjs.com/package/sonea
21 squirrel-server 0.0.1 https://www.npmjs.com/package/squirrel-server