Painlessly convert callbacks to promises and async await in javascript

Working with javascript can be frustrating for many reasons, one of them is the callback hell. In addition to callbacks making code uglier and longer, they also make it hard to work with promises or async/await.

When working with NodeJS, you will encounter many Node API functions that work with callbacks. for example, many if not all functions in the ‘fs’ module use EFC style callbacks. You can easily wrap these error first callback functions to return promises.

At the end of this article I will introduce my npm package that is written specially for this purpose. you can check it out here.

Callback Types

Continuation Passing callbacks are callbacks that do not accept errors (at least not as the first parameter).

Error-First callbacks are callbacks that accept error as their first parameter, this style is most commonly used in NodeJS.

Let’s see how we can convert fs.readdir with a promise:

function wrapped(myPath) => new Promise((res, rej) => {
fs.readdir(myPath,(error, files) => {
if (error) {
} else {
wrapped('...').then(files => ...).catch(error => ...);

What is going on?

Good news is, we can use the function with async/await syntax too:

const files = await wrapped('...');

Bad news is, we might have to write this code for many more functions, but what if there was a package for that?

Introducing callback-bender

Why Callback Bender?

  • Supports both Continuation Passing callbacks (normal) and Error-First callbacks (EFC or node style)
  • Supports wrapping callbacks that accept multiple/single/no argument(s)
  • Is pretty small
  • Provides many module formats (lib folder)
  • Provides types and a typescript version (lib folder)
  • Is tested

Getting Started

note: the default file in the package uses CommonJS (require style, mainly for node), if you need ES6 Module version (try this if in doubt) or .mjs or IIFE (var name is callback_bender) please import or use files from lib folder!

npm i callback-bender

A NodeJS fs example:

fs.readdir(path.join(...), (err, files) => { 
if(err){ ... }else{ ... }

We are using an EFC (usual for node), and we are getting one argument (files) so:

const wrapped = bend.efc.single(fs.readdir); 
// read docs to understand format, it's very easy
wrapped(path.join(...)).then(files => ... ).catch(err => ... );

More info, full examples and documentation:

Thank you for reading through, please let me know what you think.

I like to share my knowledge as a web developer, my favorite topic is Javascript.