Promises help everyone become a better developer. They can be used to replace callbacks for asynchronous operations like HTTP calls, Database queries among other things.
In this blog post, I will be sharing some of my experiences of rewriting a legacy Node.js application. This involved replacing callbacks with promises. The application runs on a MySQL database using the mysql
npm package to handle the connections.
Finding the right Promises package
Before I started the rewrite, the first task was to find a suitable package to replace the existing mysql package that uses callbacks. After looking around, I found two packages that I could use. One was node-mysql2
which meant replacing the existing mysql package. The other was node-promise-mysql
which is a wrapper for mysql
package which we were currently using. It used Bluebird
promises and the amount of code changes needed for configuring it was minimal. In the end I chose the node-promise-mysql
package.
Finding the right method to rewrite
Next, I had to find a suitable method to rewrite so that I could test the approach. It is important to choose a simple method and start small. Let us consider a method to add shops at a location categorized by state. The old code was something like this.
connection.query(checkLocation, [location], function (err, rows) { | |
if (!err) { | |
// Location exists | |
connection.query(addShop, [shopParams], function (err, rows) { | |
if (!err) { | |
// Shop added | |
connection.query(linkState, [shopParams], function (err, rows) { | |
if (!err) { | |
// Categorize with state | |
} else { | |
console.log(err); | |
callback(0); | |
} | |
}) | |
} else { | |
console.log(err); | |
callback(0); | |
} | |
}) | |
} else { | |
console.log(err); | |
callback(0); | |
} | |
}); |
As you can see, this code has the following problems,
- Need to handle errors at each query level and any conditional logic
- Possible to miss adding the error handling logic
- The code is difficult to read because of it’s nested structure
The code rewritten with promises looks like this.
connection.query(checkLocation, [location]).then(function (rows) { | |
// Location exists | |
return connection.query(addShop, [shopParams]) | |
}).then(function (rows) { | |
// Shop added | |
return connection.query(linkState, [shopParams]) | |
}).then(function (rows) { | |
// Categorize with state | |
callback(1); | |
}).catch(function(err) { | |
console.log(err); | |
callback(0); | |
}) |
Promises have the following advantages,
- Another promise is returned at the end of the first promise using a technique called Promise Chaining
node-promise-mysql
allows us to use a single method to implement the error handling logic- Code is easier to read and follow the flow
From this short example, we can see that promises are the way to go for avoiding the callback hell of Node. Bookmark this link for more Node.js articles. If there are any experiences you would like to share, please leave a comment below.