Master the fundamentals of React and Redux

Using Facebook’s Dataloader with GraphQL server

Learn to use DataLoader with GraphQL server for caching and batching requests.

This is the second article in the tutorial series on GraphQL. In this lesson, we will see how we can significantly reduce requests to our backend via batching and caching with Facebook’s dataloader. We will use the same GraphQL server that we built in the first tutorial. In case you have missed part 1, I recommend that you read it before proceeding with this tutorial.

What is caching and batching?

Caching is a process of storing data in a temporary storage area. Caching data helps prevent repetitive service calls to the backend. After being loaded once, the data is cached, eliminating redundant requests. It is a good practice to cache data that is persistent.

Batching is a way to coalesce all individual loads which occur within a single frame of execution and then calling a batch function with all requested keys. All concurrent requests will be coalesced and presented to a batch loading function. This allows your application to safely distribute data fetching requirements throughout your application and maintain minimal outgoing data requests.

Adding followersList to Github’s user object

If you have followed the previous tutorial, you already know about different data types you can use in a GraphQL schema. We defined a GraphQL schema for Github’s user entity with some of the important fields like name, email, about. We will now define another field in the Github’s user object which will represent all the followers of a user. It is intuitive to note that the type for this field should be nothing but a list of user objects. For this, GraphQL provides us with another data type called GraphQLList.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

constUserType=newGraphQLObjectType({

name:'UserType',

description:'...',

fields:()=>({

login:{type:GraphQLString},

name:{type:GraphQLString},

email:{type:GraphQLString},

about:{

type:GraphQLString,

resolve:(user)=>{

returnuser.bio

}

},

following:{type:GraphQLInt},

followers:{type:GraphQLInt},

followersList:{

type:newGraphQLList(UserType),

resolve:(user,args)=>{

return[]

},

},

}),

});

In UserType, we have added a new field called followersList that will return all the followers of the user. As per the API documentation, we can get a list of user’s followers from Github by:

1

2

3

GET/users/:username/followers

Just like we did in the previous tutorial, we will use node-fetch to get user’s followers in the resolve method.

We can clearly see a big problem in the above execution. Some of the service requests are being made multiple times.

In the next section we will see how we can avoid this problem by using a Dataloader.

Defining a Dataloader

We will first install dataloader from npm:

1

2

3

npm install--save dataloader

We will now create a DataLoader. Each DataLoader instance represents a unique cache. By default, DataLoader has an in-memory cache, but it can be easily configured to used a custom cache. For this tutorial, we will use the default cache provided by Dataloader

In index.js, import the dataloader and pass it to the GraphQL context.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

import express from'express'

import graphQLHTTP from'express-graphql'

import DataLoader from'dataloader';

import schema from'./schema.js'

constapp=express();

constuserLoader=newDataLoader()

constloaders={

user:userLoader

}

app.use(graphQLHTTP({

schema,

graphiql:true

}));

app.listen(7600);

Let’s try to start the application by running npm start. This should fail with the following error:

The DataLoader can only be constructed by passing a function that accepts keys and returns a list of promises. This function is also called a batch function. In our case, the userLoader should take a list of urls and return the fetched data from each of these urls.

Let us create this function and also move getFollowers function to index.js:

If you start the server and try running the query to get followers of followers again, you will notice that the response comes much faster this time. If you check your terminal, you will see that no two requested URLs are same. We have significantly reduced the number of requests to Github’s API.

DataLoader provides us two methods:

load(key) method takes a single key and makes a single request

loadMany(keys) method takes array of keys and make a batch request

In either case, the returned data is cached in memory.

A small exercise: Can you try using Dataloader in QueryType as well to fetch user’s data?

What’s next?

In this tutorial, we learnt how GraphQL APIs get all the data your app needs with a single endpoint. We also saw how DataLoader can be used with GraphQL for caching and batching requests. In the next tutorial, we will learn about query variables, and how and where we can use them. We will also learn about mutations and how they are different from queries.

Subscribe Now for Exclusive Content

Hi! I am Adheesh, I am a full-stack software engineer. I did my post-graduation from BITS Pilani, India where I studied Mathematics and Electrical and Electronics Engineering.

I am currently working at Myntra, which is the largest fashion e-commerce company in India. I am interested and passionate about building interactive interfaces for the web and mobile, and write performant and scalable web services.

how about covering graphql-relayjs, for connections and object identification for refetching the cached data, it will be very helpful for the beginners, starting with relayjs

WELCOME

About Eloquent WebApp

EloquentWebApp is a resource for Software engineers, Web Developers and JavaScript professionals that want to invest in their skills. Time is precious, choose a lesson and start learning something right now.