[Fixed] Handling errors with Javascript and Node.js (then/catch)

Issue

Let’s assume I have this pseudocode inside a routes.js file:

var pkg = require('random-package');

app.post('/aroute', function(req, res) {
    pkg.impl_func(data, function (err, result) {
        myFunction(entity).then(user=>{
            //DO_STUFF_HERE
            res.render('page.ejs');
        }).catch(err => {
            console.log(err);
            res.render('error.ejs');
        });
    });
});

function myFunction(username) {
   //.....
}

The pkg I used is one found on the npmjs website. myFunction() is always my function.

In my code you can see that i have implemented then/catch statement for when myFunction() fails.
So when that happens error.ejs is rendered.

But what happens when the npm package fails?
In the terminal i get the error message but there is no error handling on the server side.
This means, when it fails the user will not be notified with error.ejs, it is obvious since this functionality is omitted from my code.

But what are the ways to render error.ejs, when pkg fails?

Since I am already using .then()/.catch() technique below, can I also do it above?
In other words, can I nest .then()/.catch() statements?
Can I surround the outer code to a try/catch (while still having a try/catch inside)?

Solution

pkg.impl_func() appears to implement your typical Node.js callback interface (i.e. it returns an error as first argument in the event of an error or null if there’s no error). You can simply check for the error’s presence and render your error.ejs when it is present:

app.post('/aroute', function(req, res) {
  pkg.impl_func(data, function (err, result) {
    if (err) {
      res.render('error.ejs');
    } else {
      myFunction(entity).then(user=>{
        //DO_STUFF_HERE
        res.render('page.ejs');
      }).catch(err => {
        console.log(err);
        res.render('error.ejs');
      });
    }
  });
});

Alternatively, you can use util.promisify() to convert pkg.impl_func() into an async function. Then you can use promise.catch() or try-catch inside an async function to simplify the syntax:

const util = require('util')
const impl_func_async = util.promisify(pkg.impl_func)

// traditional promises:
app.post('/aroute', (req, res) => {
  impl_func_async(data).then(result =>
    return myFunction(entity)
  }).then(user => {
    // DO_STUFF_HERE
    res.render('page.ejs')
  }).catch(e => {
    // Will catch thrown errors from impl_func_async and myFunction
    console.log(e)
    res.render('error.ejs')
  })
})

// async-await:
app.post('/aroute', async (req, res) => {
  try {
    const result = await impl_func_async(data)
    const user = await myFunction(entity)
    // DO_STUFF_HERE
    res.render('page.ejs')
  } catch (e) {
    // Will catch thrown errors from impl_func_async and myFunction
    console.log(e)
    res.render('error.ejs')
  }
})

Leave a Reply

(*) Required, Your email will not be published