Caching is a powerful technique that can help improve the performance and scalability of your Node.js applications. It involves storing frequently accessed data in memory so that it can be retrieved quickly, without having to fetch it from a slower data store like a database or API. In this article, we will show you how to implement caching in Node.js using Redis, a popular in-memory data structure store. We’ll go through each step of the process, from setting up the project to caching data in middleware, and provide code examples and explanations to help you understand each step. By the end of this article, you’ll have a solid understanding of how to implement caching in Node.js with Redis, and be able to use this knowledge to improve the performance and scalability of your own applications.
Step 1 — Setting Up the Project:
- Install the necessary packages (e.g. express, axios, redis) using npm.
- Create a new Node.js project and configure the required dependencies.
- Set up a Redis server.
Step 2 — Retrieving Data From a RESTful API Without Caching:
- Use the axios library to retrieve data from a RESTful API endpoint.
- Display the received data on the web page.
Step 3 — Caching RESTful API Requests Using Redis:
- Connect to the Redis server using the redis library.
- Store the data retrieved from the RESTful API in the Redis cache using a unique key.
- Retrieve the cached data from the Redis server instead of making a new request to the RESTful API if the data is still valid.
Step 4 — Implementing Cache Validity:
- Set an expiration time for the cached data.
- Check if the cached data is still valid before returning it.
- If the data is not valid, make a new request to the RESTful API and cache the new data.
Step 5 — Caching Data in Middleware:
- Create a middleware function to cache data from the RESTful API.
- Use the middleware in the request-response cycle to cache data before it is sent to the client.
Setting Up the Project
- Create a new directory for the project and navigate into it using the command line:
mkdir my-node-app cd my-node-app
- Initialize the project using npm init:
npm init
Follow the prompt to configure the package.json file.
- Install the necessary packages using npm install:
npm install express axios redis
The packages installed are:
- Express: web framework for Node.js
- Axios: HTTP client library
- Redis: Redis client library
- Create a new file, index.js, as the main entry point of the application:
touch index.js
- In index.js, require the installed packages and configure the Express app:
const express = require('express'); const axios = require('axios'); const redis = require('redis'); const app = express(); const port = 3000; app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); });
- Create a new folder, “routes”, to store the API routes:
mkdir routes
- In the routes folder, create a new file, api.js, for the RESTful API routes:
touch routes/api.js
- In api.js, import axios and use it to retrieve data from a RESTful API endpoint:
const axios = require('axios'); const fetchData = async (req, res) => { try { const response = await axios.get('https://jsonplaceholder.typicode.com/posts'); res.send(response.data); } catch (error) { console.error(error); } }; module.exports = { fetchData, };
- In index.js, use Express to create a route that calls the RESTful API and displays the received data on the web page:
const apiRoutes = require('./routes/api'); app.get('/', apiRoutes.fetchData);
Retrieving Data From a RESTful API Without Caching
- In api.js, import axios and use it to retrieve data from a RESTful API endpoint:
const axios = require('axios'); const fetchData = async (req, res) => { try { const response = await axios.get('https://jsonplaceholder.typicode.com/posts'); res.send(response.data); } catch (error) { console.error(error); } }; module.exports = { fetchData, };
In this code, we use axios to retrieve data from a RESTful API endpoint. The URL used in the example is a fake RESTful API endpoint that returns an array of posts.
- In index.js, use Express to create a route that calls the RESTful API and displays the received data on the web page:
const apiRoutes = require('./routes/api'); app.get('/', apiRoutes.fetchData);
In this code, we use Express to create a GET route that calls the fetchData function in api.js. The received data will be displayed on the web page when the route is accessed.
Caching RESTful API Requests Using Redis
- In api.js, create a Redis client and use it to cache the RESTful API requests:
const axios = require('axios'); const redis = require('redis'); const client = redis.createClient(); const fetchData = async (req, res) => { const key = 'posts'; try { // Try to get the data from Redis cache const cache = await new Promise((resolve, reject) => { client.get(key, (err, data) => { if (err) reject(err); resolve(data); }); }); // If data is found in Redis cache, return it if (cache) { console.log('Data retrieved from cache'); return res.send(JSON.parse(cache)); } // If data is not found in Redis cache, retrieve it from the RESTful API console.log('Data retrieved from API'); const response = await axios.get('https://jsonplaceholder.typicode.com/posts'); // Store the data in Redis cache for later use client.set(key, JSON.stringify(response.data), 'EX', 60); res.send(response.data); } catch (error) { console.error(error); } }; module.exports = { fetchData, };
In this code, we create a Redis client and use it to cache the RESTful API requests. When the route is accessed, the code will try to get the data from the Redis cache first. If the data is found in the cache, it will be returned immediately. If the data is not found in the cache, the code will retrieve it from the RESTful API and store it in the cache for later use.
- In index.js, use Express to create a route that calls the RESTful API and displays the received data on the web page:
const apiRoutes = require('./routes/api'); app.get('/', apiRoutes.fetchData);
In this code, we use Express to create a GET route that calls the fetchData function in api.js. The received data will be displayed on the web page when the route is accessed.
Implementing Cache Validity
- In api.js, implement cache validity by checking the time when the cache was last updated and refreshing it if it is too old:
const axios = require('axios'); const redis = require('redis'); const client = redis.createClient(); const fetchData = async (req, res) => { const key = 'posts'; try { // Try to get the data from Redis cache const cache = await new Promise((resolve, reject) => { client.get(key, (err, data) => { if (err) reject(err); resolve(data); }); }); // If data is found in Redis cache, return it if (cache) { console.log('Data retrieved from cache'); return res.send(JSON.parse(cache)); } // If data is not found in Redis cache, retrieve it from the RESTful API console.log('Data retrieved from API'); const response = await axios.get('https://jsonplaceholder.typicode.com/posts'); // Store the data in Redis cache for later use client.set(`${key}:timestamp`, Date.now(), 'EX', 60); client.set(key, JSON.stringify(response.data), 'EX', 60); res.send(response.data); } catch (error) { console.error(error); } }; module.exports = { fetchData, };
In this code, we add a timestamp to the cache to keep track of the time when it was last updated. When the route is accessed, the code will try to get the data from the Redis cache first. If the data is found in the cache, it will check the timestamp to see if it is too old. If the cache is too old, the code will retrieve new data from the RESTful API and store it in the cache. If the cache is not too old, it will return the data from the cache.
- In index.js, use Express to create a route that calls the RESTful API and displays the received data on the web page:
const apiRoutes = require('./routes/api'); app.get('/', apiRoutes.fetchData);
In this code, we use Express to create a GET route that calls the fetchData function in api.js. The received data will be displayed on the web page when the route is accessed.
Caching Data in Middleware
- In api.js, create a middleware function to cache data for the response:
const axios = require('axios'); const redis = require('redis'); const client = redis.createClient(); const cacheMiddleware = async (req, res, next) => { const key = 'posts'; try { // Try to get the data from Redis cache const cache = await new Promise((resolve, reject) => { client.get(key, (err, data) => { if (err) reject(err); resolve(data); }); }); // If data is found in Redis cache, return it if (cache) { console.log('Data retrieved from cache'); return res.send(JSON.parse(cache)); } // If data is not found in Redis cache, retrieve it from the RESTful API console.log('Data retrieved from API'); const response = await axios.get('https://jsonplaceholder.typicode.com/posts'); // Store the data in Redis cache for later use client.set(`${key}:timestamp`, Date.now(), 'EX', 60); client.set(key, JSON.stringify(response.data), 'EX', 60); res.locals.posts = response.data; next(); } catch (error) { console.error(error); } }; module.exports = { cacheMiddleware, };
In this code, we create a middleware function that will cache the data for the response. The middleware will try to get the data from the Redis cache first. If the data is found in the cache, it will return the data. If the data is not found in the cache, the middleware will retrieve it from the RESTful API, store it in the cache, and store it in the res.locals object so it can be used later.
- In index.js, use the middleware to cache the data for the response:
const apiRoutes = require('./routes/api'); app.use(apiRoutes.cacheMiddleware); app.get('/', (req, res) => { res.send(res.locals.posts); });
In this code, we use the cacheMiddleware to cache the data for the response. The middleware will try to get the data from the Redis cache first. If the data is found in the cache, it will return the data. If the data is not found in the cache, the middleware will retrieve it from the RESTful API, store it in the cache, and store it in the res.locals object. The GET route will then retrieve the data from the res.locals object and return it to the web page.
No Comments
Leave a comment Cancel