Usando Axios para Consumir APIs

Exemplo Base

Há diversos momentos quando você está desenvolvendo uma aplicação Web que podem necessitar consumir e exibir dados de uma API. Há várias maneiras de se fazer isso, mas a maneira mais popular é usando axios, um cliente HTTP baseado em Promises.

Neste exercício, usaremos a API CoinDesk para exibir os preços do Bitcoin, atualizados a cada minuto. Primeiramente, precisamos instalar o axios via npm/yarn, ou através do endereço CDN.

Temos várias maneiras de recuperarmos informações de uma API, mas primeiro é interessante descobrir o formato dos dados, para sabermos o que mostraremos. Para fazer isso, faremos uma requisição para o endpoint da API, para podermos ver os dados. Podemos ver na documentação da API CoinDesk que esta chamada será feita para https://api.coindesk.com/v1/bpi/currentprice.json. Assim, criaremos uma propriedade de dados que eventualmente abrigará nossa informação e, então, recuperaremos os dados e atribuiremos usando o gatilho de ciclo de vida mounted:

new Vue({
el: '#app',
data () {
return {
info: null
}
},
mounted () {
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (this.info = response))
}
})
<div id="app">
{{ info }}
</div>

E o que temos é isso:

Veja o código Primeiro Passo com Axios e Vue por Vue (@Vue) no CodePen.

Excelente! Já temos algumas informações. Mas parece um pouco confuso agora. Então, vamos exibir adequadamente a informação desejada e também adicionar algum tratamento de exceção no caso de alguma coisa não funcionar conforme esperado ou levar mais tempo do que esperávamos para recuperar as informações.

Exemplo do Mundo Real: Trabalhando os Dados

Mostrando o Dado Desejado

É muito comum que as informações que precisaremos estejam internamente na resposta obtida, então teremos que analisar o que acabamos de obter para conseguirmos acessar adequadamente. Neste caso, podemos ver que o preço informado está em response.data.bpi. Se usarmos isso, nossa saída seria a seguinte:

axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (this.info = response.data.bpi))

Veja o código Segundo Passo com Axios e Vue por Vue (@Vue) no CodePen.

Isso é muito mais fácil para nós exibirmos, então podemos atualizar o HTML para mostrar somente a informação que recebemos. Criaremos um filter para ter certeza que a casa decimal estará no lugar correto.

<div id="app">
<h1>Preços do Bitcoin</h1>
<div
v-for="currency in info"
class="currency">
{{ currency.description }}:
<span class="lighten">
<span v-html="currency.symbol"></span>{{ currency.rate_float | currencydecimal }}
</span>
</div>
</div>
filters: {
currencydecimal (value) {
return value.toFixed(2)
}
},

Veja o código Terceiro Passo com Axios e Vue por Vue (@Vue) no CodePen.

Lidando com Erros

Às vezes, podemos não receber os dados que precisamos da API. Há vários motivos para que nossa chamada assíncrona possa falhar, seguem alguns exemplos:

Ao realizar a requisição, devemos checar todas essas circustâncias, obtendo informações em todos os casos para que possamos lidar com o problema. Em uma chamada axios, fazemos isso usando catch.

axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (this.info = response.data.bpi))
.catch(error => console.log(error))

Assim, saberemos se algo falhou durante a requisição da API. Mas, se o dado está desconfigurado ou a API está fora do ar? Neste caso, o usuário não verá nada. Podemos exibir uma informação de carregamento (um loader) durante a requisição e, em seguida, avisar o usuário se não conseguirmos recuperar os dados.

new Vue({
el: '#app',
data () {
return {
info: null,
loading: true,
errored: false
}
},
filters: {
currencydecimal (value) {
return value.toFixed(2)
}
},
mounted () {
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => {
this.info = response.data.bpi
})
.catch(error => {
console.log(error)
this.errored = true
})
.finally(() => this.loading = false)
}
})
<div id="app">
<h1>Preços do Bitcoin</h1>

<section v-if="errored">
<p>Pedimos desculpas, não estamos conseguindo recuperar as informações no momento. Por favor, tente novamente mais tarde.</p>
</section>

<section v-else>
<div v-if="loading">Carregando...</div>

<div
v-else
v-for="currency in info"
class="currency">
{{ currency.description }}:
<span class="lighten">
<span v-html="currency.symbol"></span>{{ currency.rate_float | currencydecimal }}
</span>
</div>

</section>
</div>

Você pode clicar no botão reexecutar no exemplo abaixo, para poder ver rapidamente o estado de carregamento, enquanto buscamos os dados da API:

Veja o código Quarto Passo com Axios e Vue por Vue (@Vue) no CodePen.

Isso ainda poderia ser melhorado com o uso de componentes para diferentes seções e relatórios de erros mais distintos, dependendo da API que você está usando e da complexidade da sua aplicação.

Padrões Alternativos

Fetch API

Fetch é uma API poderosa e nativa para requisições. Talvez você já tenha ouvido falar que um dos benefícios dela é que você não precisa carregar um código externo para utilizá-la, o que é verdade! Exceto… que ainda não é totalmente suportada, então você precisará de um polyfill. Existem também algumas armadilhas quando se trabalha com esta API, por isso que atualmente muitos preferem utilizar axios. Isso pode, muito bem, mudar no futuro.

Se você tem interesse em usar a Fetch API, existem excelentes artigos que explicam como fazer isso.

Considerações Finais

Existem vários caminhos para trabalhar com Vue e axios, além de consumir e mostrar um endpoint de uma API. Você também pode realizar comunicação com Serveless Functions, postar/editar/deletar de uma API que você tenha permissão de escrita, e entre outros casos. Devido à integração direta dessas duas bibliotecas, acabou se tornando uma escolha comum entre os desenvolvedores que precisam integrar clientes HTTP em seu fluxo de trabalho.