Skip to content

Latest commit

 

History

History
137 lines (92 loc) · 5.81 KB

File metadata and controls

137 lines (92 loc) · 5.81 KB

Handling errors

As a good developer, you should not only think about happy path. There are many things that can do wrong. If you are looking for a user in database, the database server might be down, or there could be network issues.

How can you handle those error scenarios?

The Express Framework offers one solution on this.

Handle errors in synchronous route handlers

Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then Express will catch and process it. For example:

app.get("/", function(req, res) {
  throw new Error("BROKEN"); // Express will catch this on its own.
});

Handle errors in asynchronous route handlers

If you call an asynchronous API in a route handler and you would like to handle errors returned/thrown by those asynchronous operations, you just need to call next(error) when some error happens. That is, you call the next callback (which is an argument of every middleware and route handler) with an instance of Error.

e.g.

app.get("/", function(req, res, next) {
  fs.readFile("/file-does-not-exist", function(err, data) {
    if (err) {
      next(err); // Pass errors to Express.
    } else {
      res.send(data);
    }
  });
});

Once Express Framework detects the argument to next call is an Error, it would skip all the other non-error-handling middlewares and route handlers on the happy path, and call Error Handlers for that request. The Error Handler can examine the error situation and return proper responses to the client side.

The signature of an Error Handler is like the one below:

function (err, req, res, next) {
}

Note that Error Handlers always take four arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the next object, you must specify it to maintain the signature. Otherwise, the next object will be interpreted as regular middleware and will fail to handle errors.

Within an error handler, you typically need to do one of two things:

  • call res.send() to generate a response, or
  • call next(err) to pass the execution to the next error handler

These error handlers are actually just middlewares. They can be registered to an app instance using the same app.use(path, middleware_function) call.

There can be multiple error handling middlewares for each request path and when error happens, they will be executed in the same order as their registration order using app.use() API.

As a best practice, we should always declare a default error handler for all requests, to ensure that handle all unforeseeable error scenarios. You define error-handling middleware last, after other app.use() and routes calls.

For example:

var bodyParser = require('body-parser')
var methodOverride = require('method-override')

app.use(bodyParser.urlencoded({
  extended: true
}))
app.use(bodyParser.json())
app.use(methodOverride())
app.use(function (err, req, res, next) {
  // logic
})

Example

Now let's take a look at one example error_handler_example.js.

node error_handler_example.js

If you visit http://localhost:3000, you should see the response generated by the error handler.

Resources

For more information on error handling, you can refer to the materials below:

There are also open-sourced error handler implementations like this one

Lab 5: Integrate a default error handler middleware for your songs routes

So far for our Songs API we have only handled the situation where user sends correct song ids to our routes. In a real life scenario for a robust API we would need to also handle error scenarios.

  • GET /songs/:id
  • PUT /songs/:id
  • DELETE /songs/:id

Requirements

Based on our understanding of error handlers, in this lab you will need to create a default error handler for your Songs API routes.

  • If user input an invalid id for GET /songs/:id, PUT /songs/:id , DELETE /songs/:id
  • Return HTTP status code 404
  • Expected response: { message: “Unable to find song with id : xx” }

You are also required to write tests to prove that the 3 routes can now handle the error condition of an invalid song id.

Instructions

  • Navigate to the express-songs-api project folder
  • Ensure that the work from your previous lab is already commited.
  • checkout to branch 9-add-error-handling to get started
git checkout 9-add-error-handling

Solution

  • After you have completed Lab 5, please commit all your work

  • You may optionally install the plugin Git History Diff for viewing the difference between git branches. This will allow you to easily compare your work with the sample solution

  • https://marketplace.visualstudio.com/items?itemName=huizhou.githd

  • Next checkout to the solution branch and we will now walk through the sample solution

    git checkout 10-add-error-handling-solution
    
  • To view the difference between your work and the sample solution go to the VS Code file explorer, right click your folder and select GitHD: View Folder Diff and select compare with 9-add-error-handling branch

  • The diff sidebar will popup and you can click on the files to view the difference between your work and the sample solution.

  • When viewing the diff you can temporarily toggle the sidebar with cmd + B to hide it.