Calling APIs in sequence using async – await.


There are certain scenarios when we want to call some APIs in sequence (order) to get some data. For example, let’s say we want to fetch data of 1000 students of a university for some analysis. The API given to us can fetch only maximum of 100 records at a time but supports pagination. Therefore, we need to call the API 10 times, one after the other to get all records.

There can be several ways to approach this problem but, in this article, we are going to solve it using async-await feature in JavaScript. Note that async await are syntactic sugar over promises and you can read more about it here.

We will create a Node.js console app and use axios library for making HTTP calls.

Setting up the project

  1. Create a source directory for your code files. Move into this directory.
  2. Fire up your terminal and execute command npm int -y. This will create a package.json file for our app.
  3. Install axios library using npm. Execute command – npm install axios.

Implementation

With our project setup, let’s start by creating an index.js file in the source directory. We are creating the index.js file just by convention. You can name it whatever you want.

We will be using an open API – “An API of Ice and Fire” for fetching data.

Let’s begin by importing axios in our file and creating a function which fetches information about GOT characters after every 500ms. We are adding a delay so as to see the data printing on our console with a time gap.

const axios = require('axios');

function getCharacters(page, pageSize) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const api = `https://www.anapioficeandfire.com/api/characters?page=${page}&pageSize=${pageSize}`;
            resolve(axios.get(api));
        }, 500);
    });
}

To demonstrate that characters are getting fetched one after the other, we will keep PAGE_SIZE to 2. We will also write another function printCharacters which will call the getCharacters function to fetch characters one after the other.

async function printCharacters(characterCount) {
    const PAGE_SIZE = 2;
    const totalCalls = Math.ceil(characterCount / PAGE_SIZE);

    for (let i = 1; i <= totalCalls; i++) {
        const response = await getCharacters(i, PAGE_SIZE);
        console.log(`
            Page Number - ${i}
            Data:
            ${JSON.stringify(response.data, null, 4)}
        `);
    }
}

Finally, let’s call the printCharacters function to make our code run.

printCharacters(10)
    .then(() => {
        console.log('All records fetched');
    })
    .catch((err) => {
        console.error(err);
    });

We will get an output like below:

            Page Number - 1
            Data:
            [
    {
        "url": "https://www.anapioficeandfire.com/api/characters/1",
        "name": "",
        "gender": "Female",
        "culture": "Braavosi",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "The Daughter of the Dusk"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [],
        "books": [
            "https://www.anapioficeandfire.com/api/books/5"
        ],
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    },
    {
        "url": "https://www.anapioficeandfire.com/api/characters/2",
        "name": "Walder",
        "gender": "Male",
        "culture": "",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "Hodor"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [
            "https://www.anapioficeandfire.com/api/houses/362"
        ],
        "books": [
            "https://www.anapioficeandfire.com/api/books/1",
            "https://www.anapioficeandfire.com/api/books/2",
            "https://www.anapioficeandfire.com/api/books/3",
            "https://www.anapioficeandfire.com/api/books/5",
            "https://www.anapioficeandfire.com/api/books/8"
        ],
        "povBooks": [],
        "tvSeries": [
            "Season 1",
            "Season 2",
            "Season 3",
            "Season 4",
            "Season 6"
        ],
        "playedBy": [
            "Kristian Nairn"
        ]
    }
]


            Page Number - 2
            Data:
            [
    {
        "url": "https://www.anapioficeandfire.com/api/characters/3",
        "name": "",
        "gender": "Male",
        "culture": "",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "Lamprey"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [
            "https://www.anapioficeandfire.com/api/houses/15"
        ],
        "books": [
            "https://www.anapioficeandfire.com/api/books/3"
        ],
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    },
    {
        "url": "https://www.anapioficeandfire.com/api/characters/4",
        "name": "",
        "gender": "Female",
        "culture": "Braavosi",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "The Merling Queen"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [],
        "books": [
            "https://www.anapioficeandfire.com/api/books/5",
            "https://www.anapioficeandfire.com/api/books/8"
        ],
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    }
]


            Page Number - 3
            Data:
            [
    {
        "url": "https://www.anapioficeandfire.com/api/characters/5",
        "name": "",
        "gender": "Male",
        "culture": "",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "Old Crackbones"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [],
        "books": [
            "https://www.anapioficeandfire.com/api/books/5"
        ],
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    },
    {
        "url": "https://www.anapioficeandfire.com/api/characters/6",
        "name": "",
        "gender": "Female",
        "culture": "Braavosi",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "The Poetess"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [],
        "books": [
            "https://www.anapioficeandfire.com/api/books/5"
        ],
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    }
]


            Page Number - 4
            Data:
            [
    {
        "url": "https://www.anapioficeandfire.com/api/characters/7",
        "name": "",
        "gender": "Female",
        "culture": "",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "Porridge"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [
            "https://www.anapioficeandfire.com/api/houses/15"
        ],
        "books": [
            "https://www.anapioficeandfire.com/api/books/3"
        ],
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    },
    {
        "url": "https://www.anapioficeandfire.com/api/characters/8",
        "name": "",
        "gender": "Male",
        "culture": "",
        "born": "",
        "died": "",
        "titles": [
            ""
        ],
        "aliases": [
            "Quickfinger"
        ],
        "father": "",
        "mother": "",
        "spouse": "",
        "allegiances": [
            "https://www.anapioficeandfire.com/api/houses/23"
        ],
        "books": [
            "https://www.anapioficeandfire.com/api/books/6"
        ],
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    }
]


            Page Number - 5
            Data:
            [
    {
        "url": "https://www.anapioficeandfire.com/api/characters/9",
        "name": "",
        "gender": "Female",
        "culture": "",
        "povBooks": [],
        "tvSeries": [
            ""
        ],
        "playedBy": [
            ""
        ]
    }
]

All records fetched

Explanation

We have created an async function printCharacters which takes total number of characters to be fetched and calls the API required number of times to get all the characters details. Note how we have used await inside a regular for loop to achieve the desired results. Even though async/await are just syntactic sugar over JavaScript promises, using them makes our code cleaner and easier to write.

Assuming that you know about async functions or have read the MDN article mentioned above, printCharacters returns a promise when called which resolves when its execution is ended, hence we are calling the then function on the Promise to print a statement when the characters data is fetched.