Como navegar entre páginas de retornos de APIs

Visão geral

Algumas APIs do Zeev tem potencial de retornar milhões de registros. Isso faz com que não seja possível resgatar todos os dados de uma vez, com uma só consulta. Se isso fosse possível, provavelmente o volume de dados trafegado seria tão grande que poderia prejudicar a experiência de todos os usuários que estão usando o sistema.

A solução para isso é que algumas APIs retornarão os dados de maneira paginada. Ou seja, a primeira consulta à API retornará um número limitado de registros, e você deverá fazer novas chamadas à essa API, informando o novo número de página, para buscar as demais informações.

Exemplo

A API de Listar todas as solicitações do sistema , por exemplo, tem potencial de retornar todas as informações geradas por todos os aplicativos do sistema. Por isso, seu retorno é paginado.

Como você pode verificar por sua documentação:

  • Há um limite máximo de registros retornados em cada solicitação, que pode variar de 30 a 100, conforme os filtros realizados;

  • Você pode modificar o número máximo de registros retornados em cada consulta através do parâmetro recordsPerPage, sempre dentro do limite máximo definido;

  • Você pode indicar a página que deseja consultar, através do parâmetro pageNumber;

A partir desses parâmetros, recomenda-se um possível seguinte algoritmo:

  • Monte um método para chamar a API do Zeev que receba por parâmetro o número da página que será pesquisada. O valor padrão é 1. Consulte a API do Zeev, enviando o número da página que será consultada;

  • Monte outro método que fará listagem de todos os registros. Defina o número máximo de páginas que você vai listar, e faça um loop no número de páginas;

  • Consulte o médoto de consulta da API em cada interação do loop;

  • Verifique em cada retorno do método da API se ocorreu erro. Se ocorreu erro, aborte;

  • Verifique em cada retorno do método da API se dados foram retornados. Se é um array vazio, não há mais dados a retornar. Aborte;

  • Utilize os dados retornados pelo método como desejar;

  • Incremente o contador de páginas para o próximo loop;

  • Implemente um método de espera / sleep para evitar problemas de rate limit em cada interação.

Veja exemplo abaixo em Node.js:

//método utilitário para aguardar um tempo em milissegundos
async function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
} 

//método para chamar a API de listagem de instâncias
async function listPageInstances(pageNumber = 1) {

    const options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            Authorization: 'Bearer <TOKEN>'
        },
        body: JSON.stringify({
            startDateIntervalBegin : "2021-01-01",
            startDateIntervalEnd : "2024-01-31",
            //definir o número de registros por página
            recordsPerPage : 100,
            //definir o número da página
            pageNumber : pageNumber
        })
    };

    const response = await fetch('http://endereco.do.zeev/api/2/instances/report', options)
    const data = await response.json();

    return data;
}

//método para listar todas as instâncias
async function listInstances() {
    
    //Total de páginas a retornar
    const totalPagesToRetrieve = 10;
    
    //Numero da pagina atual
    let actualPage = 1;
    
    //Numero do item atual
    let counter = 0;
    
    //Loop no total de páginas a retornar
    for(let i = 1; i <= totalPagesToRetrieve; i++) {
        
        //Chamada da API para resgatar os itens da página
        const data = await listPageInstances(actualPage);

        //Se ocorreu erro, abortar
        if(data.error) {
            console.log(data.error);
            break;
        }

        //Se não tem mais itens, abortar
        if(data.length === 0) {
            break;
        }

        //Loop nos itens da página
        data.forEach(instance => {
            counter++;
            console.log(`Página ${actualPage} - Item ${counter} - ${instance.id}`);
            
        });    
        
        //Incrementa a página atual
        actualPage++;

        //Aguarda 250ms para a próxima chamada para evitar rate limit
        await sleep(250);
    }
}

//Chama o método para listar as instâncias
listInstances();

Atualizado