![](https://static.wixstatic.com/media/1819a02503524d4a9d0e0538462b4fda.jpg/v1/fill/w_980,h_653,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/1819a02503524d4a9d0e0538462b4fda.jpg)
Handling Requests & Responses in Node.js REST API with Express
The following are the steps to handle the requests and responses by creating separate controllers and routers in Node.js REST API with help of Express for products service:
1. Create a new file called server.js and require the express module:
const express = require("express");
const dotenv = require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
// Defining a custom middleware function
const logger = (req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
};
// Using/Loading the custom middleware function (logger) for all requests
app.use(logger);
// Using middlewares with 'app.use()'
app.use(express.json()); // Middleware for Body parsing
app.use("/api/products", require("./routes/productRoutes")); //middleware
app.use("/api/users", require("./routes/userRoutes"));
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
|
2. Create a router for the products API. In a new file called productRoutes.js, define a router that handles requests for the products API:
const express = require("express");
const router = express.Router();
const {getProducts,
createProduct,
getProduct,
updateProduct,
deleteProduct} = require("../controllers/ProductController");
router.route("/").get( getProducts).post( createProduct );
router.route("/:id").get(getProduct ).put( updateProduct).delete( deleteProduct)
module.exports = router; |
3. Create a controller to handle the logic for the products API. In a new file called productController.js, create controller functions that handle the logic for each route in the products API:
const asyncHandler = require("express-async-handler");
//@desc Get all Products
//@route GET /api/products
//@access private
const getProducts = async (req, res) => {
res.status(200).json({message: "All Products"});
};
//@desc Create new Product
//@route POST /api/products
//@access private
const createProduct = asyncHandler(async (req, res) => {
res.status(200).json({message: "Create Product"});
});
//@desc Get Product
//@route GET /api/products/:id
//@access private
const getProduct = asyncHandler(async (req, res) => {
res.status(200).json({message: "Get Product"});
});
//@desc Update Prodouct
//@route PUT /api/products/:id
//@access private
const updateProduct = asyncHandler(async (req, res) => {
res.status(200).json({message: "Update Product"});
});
//@desc Delete Product
//@route DELETE /api/products/:id
//@access private
const deleteProduct = asyncHandler(async (req, res) => {
res.status(200).json({message: "Delete Product"});
});
module.exports= { getProducts,
createProduct,
getProduct,
updateProduct,
deleteProduct}; |
Error handling for asynchronous functions in Node.js REST API with asyncHandler
'asyncHandler' is a middleware function that simplifies error handling for asynchronous functions in Node.js REST APIs.
In Node.js, it's common to write asynchronous functions using Promises or the async/await syntax. However, these functions can throw errors that need to be handled properly to avoid crashing the application or leaking sensitive information to the client.
The asyncHandler middleware function is used to wrap asynchronous functions and handle any errors they throw. It catches the error, creates an HTTP response with the appropriate status code and error message, and passes it to the next error-handling middleware function in the Express stack.
Here's an example of how to use asyncHandler in a Node.js REST API:
import express from 'express';
import asyncHandler from 'express-async-handler';
import { getProductById } from '../controllers/productController.js';
const router = express.Router();
router.get('/:id', asyncHandler(getProductById)); |
In this example, the getProductById function is an asynchronous function that retrieves a product by ID from a database. Instead of wrapping the function in a try-catch block and handling errors explicitly, we wrap it with the asyncHandler function to handle errors automatically.
If an error is thrown by the getProductById function, asyncHandler will catch the error, create an HTTP response with the appropriate status code and error message, and pass it to the next error-handling middleware function in the Express stack. This simplifies error handling and makes the code cleaner and easier to read.
Create a constants.js file to store all constants relevant to Errors:
exports.constants = { NOT_FOUND: 404, VALIDATION_ERROR: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, SERVER_ERROR: 500, }
Finally, create our custom 'errorHandler' middleware function in the ErrorHandler.js file. If an error is thrown by one of the controller functions, asyncHandler will catch the error, create an HTTP response with the appropriate status code and error message, and pass it to the next error-handling middleware function(errorHandler) in the Express stack.
const {constants} = require("../constants")
const errorHandler = (err, req, res, next) => {
const statusCode = res.statusCode ? res.statusCode: 500;
switch(statusCode) {
case constants.VALIDATION_ERROR:
res.json({ title: "Validation Failed", message: err.message, stackTrace: err.stack});
break;
case constants.NOT_FOUND:
res.json({ title: "Not Found", message: err.message, stackTrace: err.stack});
break;
case constants.UNAUTHORIZED:
res.json({ title: "Unauthorized", message: err.message, stackTrace: err.stack});
break;
case constants.FORBIDDEN:
res.json({ title: "Forbidden", message: err.message, stackTrace: err.stack});
break;
case constants.SERVER_ERROR :
res.json({ title: "Server Error", message: err.message, stackTrace: err.stack});
break;
default:
console.log("No Errors!");
break;
}
};
module.exports = errorHandler;
|
Comments