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.
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.
JavaScript1try { 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.
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.
JavaScript1// 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.
In a full-stack application, both client and server errors require attention.
For the server, consider the following:
JavaScript1// 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.
JavaScript1import 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;
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!