No Thanks to Callback Hell

Any method that does not return instantaneously should be asynchronous. The traditional approach to designing asynchronous functions relied on callbacks. Let’s take a look at a small example and discuss the issues with this approach.

 const​ fs = require(​'fs'​);
 
 const​ displayFileContent = ​function​(pathToFile) {
 const​ handleFile = ​function​(err, contents) {
 if​(err) {
  console.log(err.message);
  } ​else​ {
  console.log(contents.toString());
  }
  };
 
 try​ {
  fs.readFile(pathToFile, handleFile);
  } ​catch​(ex) {
  console.log(ex.message);
  }
 };

We first bring in the fs library that provides both synchronous and asynchronous functions to read files. In the displayFileContent() function, we create a callback handler named handleFile. This callback function takes two parameters: err and contents. That’s the location of the first issue—is it error and data, or data and then error? There is no standardized order of the parameters; some functions may send an error first whereas others may send data as the first argument.

Within the callback handler we either print the error details or process the response and print some result. Therein lies the second issue—since we print the result right here in this handler, this function is hard to reuse. If we wanted to perform some other operations on the response before printing it, it is quite hard to extend this code to achieve that. The callback will require a callback to receive the data—this leads to what’s called callback hell. In other words, callbacks don’t compose well when a series of callbacks are necessary.

There’s a third issue with the way errors are handled. The callback handler dealt with the situation when there was an error with the file. However, readFile(), which is an asynchronous method of fs, may also blow up at the call site if the first argument is undefined or null. Again, there’s a lack of consistency in how errors are handled in callbacks. Furthermore, instead of printing the error, if we want to propagate the error to the caller, we have to deal with that in multiple places, within the callback and also in the catch block—messy.

To summarize, callback hell comes from the fact that callbacks

  • don’t compose easily for multiple levels of callbacks
  • lead to code that is hard to extend
  • have no consistency between order of parameters
  • have no consistent way to handle errors

Let’s explore how promises solve these issues elegantly.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset