1

There is a plethora of questions on Stack Overflow about NodeJS best practices when it comes to error handling best practices, specifically regarding operational errors. After an entire morning of reading articles and watching talks about best practices, I'm more confused than ever.

Here's a snippet from logic to register a new user with my service:

const registerUser = new Promise((resolve, reject) => {
  bcrypt.genSalt(10, (err, salt) => {
      if (err) {
        reject(new Error('An error occurred while generating password salt.'));
      } else {
        bcrypt.hash(user.password, salt, (err, hash) => {
          if (err) {
            reject(new Error('An error occurred while hashing password.'));
          } else {
            user.password = hash;
            user.save().then((err, user) => {
              if(err) {
                reject(new Error('An error occurred while saving the user.'));
              }
              resolve(user);
            });
          }
        });
      }
  });
}

I'm leveraging callbacks, where the first argument is an Error object. This aligns with the NodeJS docs on error first callbacks: https://nodejs.org/api/errors.html#errors_error_first_callbacks.

But the community seems to maintain that callbacks suck and lead to temples of doom like the code above. For example, there is a NodeJS best practices repo on GitHub with 19,120 stars. On the main page, contributors state:

Node.js callback style, function(err, response), is a promising way to un-maintainable code due to the mix of error handling with casual code, excessive nesting and awkward coding patterns

Source: https://github.com/i0natan/nodebestpractices#2-error-handling-practices

What gives? What's the best way to handle everyday operational errors in a NodeJS application? Are the NodeJS docs promoting anti-patterns? This seems like a simple thing that should be standardized, yet after hours of searching, I cannot find a single source of truth or accepted standard.

  • If you don't want to use callbacks, why are you using them? That section of the NodeJS docs is explaining the pattern; even if it's not the "best" way to do it, should the idiom go undocumented? – jonrsharpe Dec 15 '18 at 20:08
  • 1
    Node.js's internal APIs were created before callback fell out of vogue and *long* before async and await were options. These days the trend is promises and async, so that's often what's considered to be the best practices. The docs stay the same to maintain backwards compatibility. – Hydrothermal Dec 15 '18 at 20:11
  • @jonrsharpe I'm using them because the NodeJS docs use them. I'm open to using promises and async/await and I understand their benefits over callbacks, but I am/was hesitant because the docs seem to reinforce using callbacks –  Dec 15 '18 at 20:19
  • @Hydrothermal thanks for the comment. I'll probably end up using async await and promises, but it just seemed weird that the docs list callbacks as the main practice. I get maintaining backward compatibility, but ideally the docs should clearly communicate the difference between past and current best practices, which I don't feel they do, leading to my confusion –  Dec 15 '18 at 20:23
  • @StookOverflook No problem. The issue is really that the docs have no interest in best practices; their only purpose is documenting how Node.js does things. The internal Node.js APIs are not always necessarily good examples of how things *should* be done, so you should always be a little cautious of mimicking the docs. – Hydrothermal Dec 15 '18 at 20:25
  • Also because the core APIs *are* all written to take error-first callbacks. You can wrap them in promises if you want to (see e.g. https://stackoverflow.com/a/51112228/3001761), but that's not going to actually change the underlying API. – jonrsharpe Dec 15 '18 at 20:26
  • @MarkMeyer thanks, I updated the code by wrapping the whole thing in a promise and using resolve/reject –  Dec 15 '18 at 20:28
  • Why? Bcrypt's isn't part of the core NodeJS APIs, and it *does* support promises directly (*as well as* the callbacks). – jonrsharpe Dec 15 '18 at 20:33
  • I'll just rewrite my logic using the promises directly supported by bcrypt, I just needed a quick example. My question is answered, which is basically that NodeJS docs aren't the place to go for best practices. Feel free to throw up an answer and I'll accept it –  Dec 15 '18 at 20:44
  • @StookOverflook I think the real lesson to learn is that in many (if not most) cases there is not one "best practice". There is tons of smoothly-running, well-maintained code that uses the callback pattern and tons of spaghetti-code built on promises. Promises and async/await are relatively new to the ecosystem. – Mark Dec 15 '18 at 21:01

0 Answers0