5 formas de fazer requisições HTTP em Node.js usando Async/Await

March 19, 2020
Escrito por
Sam Agnew
Twilion

5-formas-de-fazer-chamadas-http-em-node-js-usando-async-await.png

Realizar chamadas HTTP é uma funcionalidade básica nas linguagens modernas, e uma das primeiras coisas que muitos desenvolvedores aprendem quando estão iniciando em novos ambientes de desenvolvimento. Quando pensamos em Node.js, existem uma quantidade considerável de soluções para este problema construídas dentro da própria linguagem e pela comunidade. Vamos ver algumas das soluções mais populares.

Alguns anos atrás, escrevi um post similar sobre este tópico, mas agora que a funcionalidade de async/await é mais difundida e popular em códigos JavaScript, fazer chamadas de rede é mais simples que nunca. Além disso, Request, a biblioteca HTTP mais popular para Node foi descontinuada. Então é hora de um guia mais atualizado!

Nós usaremos a API de Foto Astronômica do Dia (APOD) da NASA como uma API JSON que utilizaremos em todos os exemplos, porque o espaço é a coisa mais legal de todos os tempos.

Pizza GIF

Antes de continuar, você precisa se certificar que possui a versão atualizada do Node.js e npm instaladas na sua máquina.

HTTP – a Biblioteca Padrão

Com o propósito de comparar, vamos começar vendo como funciona o módulo HTTP padrão sem Promises e async/await. Com este módulo, você tem a vantagem de não se basear em nenhuma dependência, mas ele não é muito amigável para o desenvolvedor, se comparado com outras soluções.

O código a seguir vai enviar uma requisição GET para a API da NASA e mostrar a URL da foto astronômica do dia, assim como sua explicação:

const https = require('https');

https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', (resp) => {
  let data = '';

  // Um bloco de dados foi recebido.
  resp.on('data', (chunk) => {
    data += chunk;
  });

  // Toda a resposta foi recebida. Exibir o resultado.
  resp.on('end', () => {
    console.log(JSON.parse(data).explanation);
  });

}).on("error", (err) => {
  console.log("Error: " + err.message);
});

Boa parte da funcionalidade do módulo HTTP e HTTPS é muito baixo-nível. Você é obrigado a receber os dados de resposta em blocos e vai ter que explicitamente aguardar que todos os dados sejam recebidos. Você também precisará tratar os dados recebidos manualmente. Este módulo também não suporta HTTPS por padrão, então precisamos requerer o módulo https no luar, se a API que estiver usando comunicar através de HTTPS. Embora você não possa utilizar a feature de async/await em chamadas HTTP feitas com essa biblioteca, você poderia potencialmente usar streams assíncronos para fragmentar os dados recebidos.

Pode dar um pouco mais de trabalho para receber os dados que você quer, mas pode ser útil se você não quer adicionar muitas dependências na sua base de código ou quer acesso às funcionalidades de baixo nível.

Got

Got é outra opção se você precisa de uma biblioteca mais leve. Ela foi desenvolvida para ser amigável e também também está disponível para usar na Twilio Functions.

Instale o Got com npm:

npm install got@9.6.0

Porque o Got usa promises, você verá que precisa de muito menos código para fazer a mesma tarefa que fizemos acima. E você também pode tirar vantagem das chamadas com async e await:

const got = require('got');

(async () => {
  try {
    const response = await got('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', { json: true });
    console.log(response.body.url);
    console.log(response.body.explanation);
  } catch (error) {
    console.log(error.response.body);
  }
})();

Esta biblioteca não trata JSON por padrão, então precisamos adicionar { json: true } como um argumento ao criar a chamada. Got é uma opção fantástica se você precisa de uma biblioteca fácil e que lide com chamadas HTTP de um jeito sensato.

Axios

Axios é outro cliente HTTP baseado em Promises que funciona no navegador e também no Node.js.

Para instalar o Axios pelo npm, digite o seguinte comando no seu terminal:

npm install axios@0.21.1

O código a seguir vai realizar a mesma tarefa de exibir a URL e a explicação da foto astronômica do dia:

const axios = require('axios');

(async () => {
  try {
    const response = await axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY')
    console.log(response.data.url);
    console.log(response.data.explanation);
  } catch (error) {
    console.log(error.response.body);
  }
})();

Axios também trata respostas JSON por padrão. Muito conveniente! Você também pode fazer múltiplas requisições simultâneas com axios.all, se você quiser fazer algo como carregar a foto astronômica de dois dias diferentes ao mesmo tempo:

const axios = require('axios');

(async () => {
  try {
    const [response1, response2] = await axios.all([
      axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2020-03-18'),
      axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2020-03-17')
    ]);
    console.log(response1.data.url);
    console.log(response1.data.explanation);

    console.log(response2.data.url);
    console.log(response2.data.explanation);
  } catch (error) {
    console.log(error.response.body);
  }
})();

SuperAgent

Similar ao Axios, SuperAgent é outra biblioteca popular utilizada principamente para fazer requisições assíncronas no navegador, mas que também funciona no Node.js. Instale o SuperAgent com o seguinte comando:

npm install superagent@6.1.0

O que é legal sobre o SuperAgent é que você tem outras funções muito úteis que você pode encadear na requisição, como a query() para adicionar parâmetros na chamada. Nos exemplos anteriores, estávamos adicionando esses parâmetros manualmente na URL, mas veja que agora o SuperAgent oferece uma função para fazer isso:

const superagent = require('superagent');

(async () => {
  try {
    const queryArguments = {
      api_key: 'DEMO_KEY',
      date: '2020-03-18'
    }

    const response = await superagent.get('https://api.nasa.gov/planetary/apod').query(queryArguments)
    console.log(response.body.url);
    console.log(response.body.explanation);
  } catch (error) {
    console.log(error.response.body);
  }
})();

Assim como no Axios, você não precisa tratar a reposta JSON você mesmo, o que é bem legal.

node-fetch

node-fetch é um módulo leve que traz a biblioteca window.fetch do Node.js usando o mínimo de código.

Assim como nos exemplos anteriores, instale o node-fetch com o seguinte comando:

npm install node-fetch@2.6.0

As versões mais recentes dessa biblioteca utiliza promises, então também podemos usar a sintaxe async/await com ela:

const fetch = require('node-fetch');

(async () => {
  try {

    const response = await fetch('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY')
    const json = await response.json()

    console.log(json.url);
    console.log(json.explanation);
  } catch (error) {
    console.log(error.response.body);
  }
})();

Esta biblioteca possui uma função integrada para converter a resposta para JSON, mas não faz isso de forma automática da mesma forma que o Axios e o SuperAgent fazem. Esta é uma ótima biblioteca para pessoas que estão acostumadas a usar a API Fetch no navegador.

Considerações Finais

Este artigo não cobre todas as soluções, mas agora você pode ver como a funcionalidade básica funciona em algumas das bibliotecas HTTP mais populares no Node.

Outras linguagens possuem uma variedade de bibliotecas similares para lidar com este problema. Confira este outros tutoriais para Swift, Python e Ruby. Verifique também nossos Guias rápido de Node.js para testar seus novos conhecimentos.

Quais são suas formas favoritas de fazer chamadas HTTP? Fique a vontade para falar comigo e tirar dúvidas: