Lesson 6

Crafting Robust Applications: Error Handling in Node.js and Express.js

Lesson Overview

In this session, we're delving into error handling within Node.js and Express.js. As a robot needs instructions for instances when an object cannot be found, our code similarly requires mechanisms for handling errors.

Introduction to the Try/Catch Block

Error handling is a procedure that detects and manages errors during program execution. Unhandled errors, generated by Syntax Errors (breaches of JavaScript rules), and Runtime Errors (exceptions during execution), can disrupt programs — akin to a robot attempting to find a non-existent object.

The try statement examines a block of code for errors. Any existing errors are "caught" by the catch block, thus providing error management.

1try { 2 // Attempts to print 'num' 3 console.log(num); 4} catch (err) { 5 // If an error occurs (e.g., `num` wasn't defined), it's caught, and an error message is printed 6 console.log(err.message); 7}

In this piece of code, instead of letting the program crash (due to the issue that num is not defined), we "catch" the error and handle it gracefully.

Error Responses in API

Effective error handling enhances user experience by utilizing appropriate HTTP status codes (e.g., HTTP 200 signifies success, HTTP 404 denotes a resource not found, HTTP 500 denotes an internal server error) within the API.

1// Endpoint for retrieving user data by ID 2app.get('/api/user/:id', (req, res) => { 3 try { 4 const user = getUserById(req.params.id); 5 if (!user) { 6 // If the user was not found, return status 404 7 res.status(404).json({message: "User not found"}); 8 return; 9 } 10 res.json(user); 11 } catch (err) { 12 // If an error occurs, a response with status code 500 is sent 13 res.status(500).json({ error: "Server error" }); 14 } 15});

In this context, we use try/catch for handling server-side exceptions, and catch dispatches an HTTP status code 500 (Internal Server Error) for server errors.

Error Handling in a Full-Stack Application

In a full-stack application, both client and server errors require attention.

For the server, consider the following:

1// API endpoint that attempts to update a user's details 2app.put('/api/user/:id', (req, res) => { 3 try { 4 const user = updateUser(req.params.id, req.body); 5 // rest of the code 6 } catch (err) { 7 // If an error occurs, an error response is sent 8 res.status(500).json({ error: 'Failed to update user' }); 9 } 10});

On the client side (React with Axios), the catch block manages errors during the GET request.

1import React, { useEffect } from 'react'; 2import axios from 'axios'; 3 4function App() { 5 useEffect(() => { 6 // This function will be triggered after the component is mounted 7 axios.get('/api/user/123') 8 .then(res => { 9 // Handle success 10 }).catch(err => { 11 // Error during GET request is handled here 12 console.error(err.message); 13 }); 14 }, []); 15 16 // Rest of the functional component code 17 18 return ( 19 // Your JSX here 20 ); 21} 22 23export default App;
Lesson Summary

Today, we have covered error handling, try/catch blocks, error handling in APIs, and a full-stack application. By avoiding application crashes and providing valuable feedback, proper error handling proves beneficial. Prepare for forthcoming practice tasks, where your learning is enhanced by practical application. Remember, to err is human; to handle is divine!

Enjoy this lesson? Now it's time to practice with Cosmo!

Practice is how you turn knowledge into actual skills.