In this article, we are going to create a simple ExpressJS project which will call a starwars
API to fetch its movie character details. This API is provided by Swapi . You can find the code for this at Github .
Installing Redis
Redis is an open-source, key-value database. It is widely used for caching as an in-memory data structure. It can also be used as a persistence database.
Windows
On windows, you can install Redis by downloading it from github.com/dmajkic/redis/downloads after unzip run the executable file.
Mac
On Mac, you can use a Homebrew package manager.
If homebrew is not already installed you can install it by running the following command
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Once Homebrew is installed you can install Redis
brew install redis
Docker
The best way to get Redis running quickly on any operating system is using Docker.
Once docker is successfully installed you can execute the following command to run Redis in the background.
docker run --name some-redis -d redis
Setting up our project
Let's start by creating our project directory and cd
into it.
mkdir starwars-redis-express
cd starwars-redis-express
Initialize a NodeJS project passing the -y
flag which accepts all the defaults.
npm init -y
For this project, we will use ExpressJS as our web framework, Node Fetch library to call starwars API, and Redis library to communicate with Redis.
Install express, node-fetch, and Redis
npm i express node-fetch redis
Install nodemon
as a dev dependency so that we don’t have to manually restart the server again and again after every change.
npm i -D nodemon
Open package.json
and add a script like this
"scripts": {
"start": "nodemon index"
}
Now let's create a simple express server.
Create index.js
file
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/startwars/people', (req, res) => {
res.send('Star Wars');
});
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
});
Now let's run the server by executing the command npm run start.
If you visit http://localhost:3000/starwars/people
you should see a text Star Wars on your browser.
The endpoint is startwars
because we are going to consume Star Wars API from swapi.co in this example app.
Let’s call the star wars actual API to fetch the results and send them to the client.
First import the nodefetch libaray
const fetch = require('node-fetch')
create an async
function to call startwars API.
const getPeople = async (req, res, next) => {
try {
const { id } = req.params;
console.log(`Fetching people data for id ${id}`);
const response = await fetch(
`https://swapi.co/api/people/${req.params.id}`
);
const people = await response.json();
res.send(getResponse(people));
} catch (err) {
console.error(err);
res.status(500);
}
};
Implement the getResponse function use above
const getResponse = (people) => {
const { name, height, gender } = people;
return `
<ul>
<li>Name: ${name}</li>
<li>Height: ${height}</li>
<li>Gender: ${gender}</li>
</ul>
`;
}
Change our API definition to include id
as the URL parameter
app.get('/startwars/people/:id', getPeople);
Above API calls the getPeople
function which then calls the starwars
API to fetch person data by id
.
Now if you visit URL http://localhost:3000/startwars/people/1
you should get a below response
If you check the network logs in the browser our API call approximately take 2 sec to respond.
Now let's add caching to our API to make it faster
Import the Redis package
const redis = require('redis');
Connect to Redis client
const REDIS_PORT = process.env.REDIS_PORT || 6379;
const client = redis.createClient(REDIS_PORT);
Create a middleware function to return the cached response if available
const cachePeople = (req, res, next) => {
const { id } = req.params;
client.get(id, (err, data) => {
if (err) throw err;
if (data !== null) {
res.send(getResponse(JSON.parse(data)));
} else {
next();
}
});
};
This function checks if there is an entry against the id in Redis. If it finds one it will return the cached result other will return next() which will allow continuing with the normal API call.
Change the API call line to make use of the above middleware.
app.get('/startwars/people/:id', cachePeople, getPeople);
Last we need to add a line in our getPeople
function right before we send the response to the client to set an entry in Redis after fetching result from starwars
API.
client.set(id, JSON.stringify(people), 'EX', 3600);
res.send(getResponse(people));
This will create a cache entry with key id
for 3600 sec.
Now if you visit the URL http://localhost:3000/startwars/people/1
first time it will take around ~2sec to load if you refresh it you will see response time will be less than ~10ms
If you change the id
from 1 to 2 again the first response time will be high but further requests will be served from the cache until the cache entry expires.
That’s it, you check out the code on GitHub.
This article is inspired by Brad’s video tutorial youtube.com/watch?v=oaJq1mQ3dFI. Follow it to learn a lot of cool things.
Thanks