2

I have a helper function that hits an API and fetches a page by ID. It uses async/await and I am trying to handle errors with try catch.

To test the error handling I am purposefully giving it an ID that does not exist.

Here is the method:

  const findPage = async (req, res, pageId) => {
    let document
    try {
      let response = await getByID(pageId)
      if (!response) throw Error('No Response')
      return document
    } catch (error) {
      console.log(error) // I can see the error is being thrown.. I am purposefuly giving it an id that does not exist
      return error
    }
  }

It does indeed throw an error like I expect. However, I am calling the function in another part of the app using an express Route.

Router.route('/page/:id').get(async (req, res) => {
  let results
  try {
    results = await findPage(req, res, req.params.id) // This Function Returns an error
    // Yet we still get results
    res.json({results, msg: 'WHY?'})
  } catch (error) {
    res.send(error)
  }
})

In the same Router file, I have attempted to add some specific middleware to this Router as well, but as there is no error, it is never triggered.

Router.use((err, req, res, next) => {
  if (err) {
    console.log('holy error')
  } else {
    console.log('no error')
  }
  next(err)
})

How can the express API call return results, and not the error, when the function it is calling itself returns an error?

2 Answers2

1

What I can see from your code is that your try/catch block inside the Router.route is not catching an expetion of findPage function, and that is becasue you are also catching an exception inside that findPage and just simply returning an error rather than throwing an exception;

try {
  results = await findPage(req, res, req.params.id) // This Function Returns an error
  // Yet we still get results
  res.json({results, msg: 'WHY?'})
} catch (error) {
  res.send(error)
}

So inside findPage if you really need to do something when excptions happening then you have to catch it and if you like the calller also catch the expetion you need to throw the same erro or a new more context-aware error again. Otherwise if you dont do any action when exception happens you dont need to catch it.

const findPage = async (req, res, pageId) => {
    let document
    try {
      let response = await getByID(pageId)
      if (!response) throw Error('No Response')
      return document
    } catch (error) {
      // do something here if you really need to otherwise you dont need to catch exceptions here
      // then rather than `return error` you should 
      throw error
    }
  }
Nesa Mouzehkesh
  • 3,755
  • 2
  • 14
  • 11
0

You are catching the error in findPage() which means the error won't propagate up the call stack. You are just returning the error like a normal value, which will end up in the variable results in your Routes function. If you want to deal with the error in both places you need to throw it again in findPage():

async function callee(){
  try {
    throw("Some Error")
  } catch(err) {
    console.log("caught error in callee:", err)
    throw(err)
  }
}
async function caller(){
  try {
   let val =  await callee()
   console.log("returned value", val)
  } catch (err) {
    console.log("caught error in caller: ", err)
  }
}

caller()

If you don't want to deal with it on both places, catch it in the function that's responsible for handling errors:

async function callee(){
  throw("Some Error")
}
async function caller(){
  try {
   let val =  await callee()
   console.log("returned value", val)
  } catch (err) {
    console.log("caught error in caller: ", err)
  }
}

caller()
Mark
  • 90,562
  • 7
  • 108
  • 148