Welcome folks I am back with another blog post. In this blog post we will be building a cache service in Node.js with the help of Redis Library. Redis is a nice library if you want to save your data in cache so that when you use that cache data in future calls to your application. This increases performance level of the application as less external calls are made and we are fetching data from the cache. To fully understand the concept of Redis we will be making a http request to the github api and storing that data in cache. We will be fetching the no of repositories for a username in github and then saving the data in the Cache with the help of Redis. Let’s get started with the post.

Prerequisites

There are some prerequisites for this tutorial. These are as follows:

Node: You should have basic knowledge of Node. Javascript: You should have a good understand in writing javascript code.

Requirements

There are some requirements for this tutorial. These are as follows:

Node: You should have node installed on your computer. Visual Studio Code: You should have a text editor where you will writing your code. I am using visual studio code for this project. Redis: You should have Redis Server installed so that we can cache the data in our application. I will be illustrating how to install Redis on windows as i am using windows machine to make this project.

Installing Redis

To install Redis on Windows just click this link and download the zip file. Extract the zip file and run the executable Redis server file. This is will run the redis server for you. The screenshots of installing windows are given below.

As you can see the Redis server is started. Just minimize the window and it will run in the background.

After starting the redis server. we also need to start the redis cli to have some debugging in our application. Also start the redis-cli executable stored in the same folder.

The redis cli is started on the port number 6379. You port number may be same or different.

Configuring Project

Now make a simple directory where you want to make the project. Go inside the directory and initialize the npm init command to generate the package.json file for the project.

Now after making the package.json file now we will installing dependencies for the project. There are namely three dependencies

Express : Express will be the server on which the app will be running Node-Fetch: This will be used to make http requests to the Github API. Redis: This will be the driver which is required to connect the Redis server and Node.js. Nodemon: This will be the module which will be required to automatically restart the server when any kind of changes are made to the application.

After installing all these dependencies our package.json file will look something like this:

Now after installing all the dependencies just create the index.js file which will be the starting point of our project. This file will contain all the code that we will write in this application.

First of all in this index.js file we will first of all import all the dependencies of the project i.e express, node-fetch and redis driver into our node project. This is done by the require function. And then we will start the express app at a port number which is shown below.

const express = require('express'); const fetch = require('node-fetch'); const redis = require('redis'); const PORT = process.env.PORT || 5000; const REDIS_PORT = process.env.REDIS_PORT || 6379; const client = redis.createClient(REDIS_PORT); const app = express(); app.listen(5000,() =>{ console.log(`App listening on PORT ${PORT}`); })

In this block of code we are fetching the dependencies by require function and then we are setting the ports for express app and also for the redis server. And then we are creating the redis client by calling the redis.createClient method and passing the actual redis port number. And after that we are actually creating the express app by calling the express() function and storing that reference in the app variable.And lastly we are listening on Port number 5000 for the express app and printing out on the console.

So when you run this script by going to command prompt by nodemon. Just write the command nodemon index.js as shown below.

So you can see that after running the command we are seeing the result on the console that app listening on port 5000. So if we open the url in the browser http://localhost:5000 we shall get an error like this

This error i.e. cannot get/ comes because we have not configured the routes for the application. That is why when we open the home page route it is saying nothing found no route was configured. After this we will be configuring routes for the application.

Now we will making the route for the homepage. Whenever anyone open the homepage we want to fetch data from github about the repository of a certain username that we pass to the api. For that we will create a custom middleware function which will handle that specifically. We will create a custom function getRepos() as shown below. This function will be async function

app.get('/repos/:username',getRepos); async function getRepos(req,res,next) { }

This async function takes three parameters namely request, response and the next function which will continue the flow after the middleware is over and it will hands the flow to the actual request

In this function we will be using the try catch block in order to catch the errors which will be coming as this is a async function. So the first thing we will do is print some kind of message on the console so that we can know the data is being fetched. Secondly we will be extracting the request parameter that is passed alongside with the request. In this case this is username we store it in variable username. Lastly we call the fetch function which is await pass the full url of the github api and also adding the request paramter i.e. username to get the response and store it in response variable. We are converting the response which is coming from the api to json with the help of response.json() method and then we are sending that response back to the browser by res.send(data) method passing the actual json data.

async function getRepos(req,res,next) { try{ console.log("Fetching Data"); const {username} = req.params; const response = await fetch(`https://api.github.com/users/${username}`); const data = await response.json(); res.send(data); }catch(err){ console.log(err); } }

So when we run this script after running nodemon index.js and open the url http://localhost:5000/repos/bradtraversy which is the actual url to hit the github api where we passing the username bradtraversy. This will send out a json response which contains all the repository of the username bradtraversy something like this as shown below.

So this is the json response which is returned by the api. So we need to save only the no of public repos that the user have so we will store that in the redis cache.

So we will set this public_repos data into a variable and set in redis cache.

const repos = data.public_repos; client.setex(username,3600,repos);

So here in this block of code we are first of all fetching the public_repos number and storing that in repos variable and secondly we are storing it redis cache by calling method on the client variable which holds the redis driver reference and it has a method called client.setex() which actually takes three arguments to set the cache the first argument will be the name of the cache variable in this case we are giving the username variable in this case the username will be bradtraversy and second argument is the time duration for which you want to cache to exist in the browser. We are passing here 1 hour i.e. 3600 seconds. And last argument is the actual data which is to be stored in the cache so in this case this is the total number of public repos to store for the user.

And after that we will now only send the total number of public repositories in the response so we will create a custom function setResponse() for achieving this. This function takes two arguments namely the username and the repos.

res.send(setResponse(username,repos)); function setResponse(username,repos) { return `<h2>${username} has ${repos} Github Repos</h2>`; }

Here we are using in this function a template string and we are printing out the username has x number of github repositories in h2 tag. A clean way to return the result back to the browser. But actually we are not using the cache that we have stored earlier. We are again returning this result from the api. If you open the url http://localhost:5000/repos/bradtraversy on the browser again you will see something like this.

Now if I open my developers console on the browser you can find out that the time required to fetch this result is more because we are not using any kind of caching mechanism in this case redis so the time required is more as compared to the case when we use redis later.This is shown below.

So you can see the time shown in the network tab of the developers console of the browser. 409 ms is taken every time to fetch these results. This is a bad user experience and also every time you have to make the same request again and again to fetch the same results. And some Api providers restricts the usage of how many api requests you can make per hour. In both these scenarios redis can save you big time.

Now we will be implementing the redis caching mechanism by adding another middleware function which again takes three arguments req, res, and next function to get the control back to the request.

// cache middleware function cache(req,res,next) { const {username} = req.params; client.get(username,(err,data) =>{ if(err) throw err; if(data !== null) { res.send(setResponse(username,data)); } else{ next(); } });

This cache middleware consists of a cache function in which we are taking three arguments request, response and next function and in that we are first of all grabing the username from the request paramter. And then we are calling the client.get() method passing the actual username value to it. This function will return the actual value of the cache which is stored for this name. And also the second argument is the callback function which takes two arguments error and data. Error holds any kind of error which takes place during the process. If any kind of error is there we can throw the error or else we can send the data if it is not null to the browser by again calling the setResponse() method which is a method which we made earlier.And in the else block we are calling the next function if data is null. This will now take data from the cache and not from the api again and again. This is significantly reduce the time taken for the application to retrieve the data.

Now if you open the url again http://localhost:5000/repos/bradtraversy now and open developers console and in the network tab you will find that the time taken to retrieve the result is so less. It is shown below.

So you can see above it only took 8ms this time to return the result. Thisis a big difference compared to the earlier case. In this case we are fetching from the redis cache. This can greatly improve the performance of our application and also improve user experience. And also your problem of restricted usage of the api is also solved as you will make less api calls.

Full Source Code

Wrapping it up. The application is complete. The whole source code of the application is given below.

index.js

const express = require('express'); const fetch = require('node-fetch'); const redis = require('redis'); const PORT = process.env.PORT || 5000; const REDIS_PORT = process.env.REDIS_PORT || 6379; const client = redis.createClient(REDIS_PORT); const app = express(); // cache middleware function cache(req,res,next) { const {username} = req.params; client.get(username,(err,data) =>{ if(err) throw err; if(data !== null) { res.send(setResponse(username,data)); } else{ next(); } }); } app.get('/repos/:username',cache,getRepos); async function getRepos(req,res,next) { try{ console.log("Fetching Data"); const {username} = req.params; const response = await fetch(`https://api.github.com/users/${username}`); const data = await response.json(); const repos = data.public_repos; client.setex(username,3600,repos); res.send(setResponse(username,repos)); }catch(err){ console.log(err); } } function setResponse(username,repos) { return `<h2>${username} has ${repos} Github Repos</h2>`; } app.listen(5000,() =>{ console.log(`App listening on PORT ${PORT}`); })

package.json