简体   繁体   中英

Error handling in ExpressJS middlewares, next() vs throw

I'm trying to understand handling errors in express. TrustIP function is a middleware, which pass the error by calling next(new Error('err')) , but is also possible to do this with throw new Error . Both seems to work, what's the correct way to do this and why? I'm still learning. Thanks for your time.

function trustIP(req, res, next) {
  const trustedIPs = ['**.**.**.**']
  let requestIP = req.headers['x-forwarded-for'] || req.socket.remoteAddress
  if (requestIP.substr(0, 7) === '::ffff:') {
    requestIP = requestIP.substr(7)
  }
  if (trustedIPs.indexOf(requestIP) >= 0) {
    next()
  } else {
    next(new Error(`Not trusted IP: ${requestIP} tryed to connect`))
    // throw new Error ???
  }
}
app.use('/', trustIP, navRoutes)
app.use(errorHandler)
app.listen(process.env.PORT, () => console.log(`Server on port: ${process.env.PORT}`))
const errorHandler = (err, req, res, next) => {
  console.error('error handler:', err.stack)
  res.status(500).send(err.message)
}

Per the docs , they basically do the same thing. However, in an asynchronous (function invoked in handler with callback in this context) function (eg fs.readFile ) you will need to use the callback and pass your error inside.

// synchronous, just throw
app.get('/', (req, res) => {
  throw new Error('BROKEN') // Express will catch this on its own.
})

// asynchronous, pass to callback
app.get('/', (req, res, next) => {
  fs.readFile('/file-does-not-exist', (err, data) => {
    if (err) {
      next(err) // Pass errors to Express.
    } else {
      res.send(data)
    }
  })
})

I haven't tested this myself, but I'm pretty sure this is because if no error is actually thown and the error is only visible via the parameter of the callback (of say fs.readFile ), no response will ever be sent to the client and they will wait for a response forever.

In your trustIp function, next(new Error('err')) and throw new Error('err') would do exactly the same thing.

You can prove this by putting a breakpoint in your trustIp function and examining the code in express that calls it. This is what you will find there:

try {
  fn(req, res, next);
} catch (err) {
  next(err);
}

If your function throws an error, express simply catches it and calls the next function.

But it's important to understand that the situation becomes different if you make trustIp into an async function. In that case, it's no longer a function that throws an error, but rather a function which returns a promise which will reject. That's a different thing, and express (version 4) does not know how to handle it. That's why calling next(err) in your code is generally a good habit to get into when using express.

So, in general, the difference between handling an error and rethrowing the error is in the question of whose responsibility is it to handle it.

Case 1) Imagine you create an API where you enter a phone number into an input field. The method does not take letters. It only takes numbers. At this time, you would assume that the programmer who is using your code needs to pass the error back to the user and tell them that they can only enter numbers. The user though enters letters. At this point, you would throw the error back to the person who calls it so they can tell the user to correct it.

Case 2) An error is handled when something happens due to something that is out of the control of the person who calls it, then the code handles the error by logging it and maybe bringing up a page. This might happen if a server is down, and your call depends on whether a server is up. At that point, you handle the error with a meaningful error code telling the user roughly what is going on. There is nothing the caller of your method can do to resolve it. When you handle an error, put as much information in the logs as possible for the person who will debug this so they can figure out why the problem occurred.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM