user1584421
user1584421

Reputation: 3863

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

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)?

Upvotes: 0

Views: 280

Answers (2)

Joseph
Joseph

Reputation: 119877

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')
  }
})

Upvotes: 2

charlietfl
charlietfl

Reputation: 171700

You could use a simple try/catch to wrap it all and render error.js in that catch also.

As for nesting try/catch...yes you can. In this case however a promise catch() is slightly different than a basic try/catch

app.post('/aroute', function(req, res) {

      try {
        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');
          });
        });

      } catch (e) {
        res.render('error.ejs');
      }
    });
});

Upvotes: 0

Related Questions