Fetch API e o JavaScript
A API Fetch é mais uma API que veio para nos ajudar e facilitar certos trabalhos repetitivos.
No lugar de usarmos os antigos objetos XMLHTTPRequest, podemos usar a API fetch para lidar com requisições HTTP.
Promise
Uma coisa muito legal é que a Fetch API segue o padrão de Promise.
const URL_TO_FETCH = 'https://braziljs.org/api/list/events'; | |
fetch(URL_TO_FETCH, { | |
method: 'get' // opcional | |
}) | |
.then(function(response) { | |
// use a resposta | |
}) | |
.catch(function(err) { | |
console.error(err); | |
}); |
`Simples assim… ou nem tanto!
Como tratar a resposta do fetch
A resposta retornada pelo fetch trata-se de um objeto Response
. Este objeto tem diversas métodos extremamente úteis, dentre eles, o método text()
, o qual podemos usar para recuperar a informação retornada pela requisição, no formato texto. Este método nos retornará uma Promise que, quando resolvida, nos entregará o conteúdo da requisição:
const URL_TO_FETCH = 'https://braziljs.org/api/list/events'; | |
fetch(URL_TO_FETCH, { | |
method: 'get' // opcional | |
}) | |
.then(function(response) { | |
response.text() | |
.then(function(result) { | |
console.log(result); | |
}) | |
}) | |
.catch(function(err) { | |
console.error(err); | |
}); |
Fetching JSON
O objeto Response também tem o método json
, que também retorna uma promise, para facilitar caso esteja acessado uma API JSON.
fetch(URL_TO_FETCH).then(function(response) { | |
response.json().then(function(data) { | |
console.log(data); | |
}); | |
}).catch(function(err) { | |
console.error('Failed retrieving information', err); | |
}); |
Usando syntaxe ES2015 (ES6)
Podemos nos utilizar das atualizações da linguagem, como uso de arrow functions, além de otimizar a forma como lidamos com promises, evitando encadeamento.
fetch(URL_TO_FETCH) | |
.then(response => response.json()) // retorna uma promise | |
.then(result => { | |
console.log(result); | |
}) | |
.catch(err => { | |
// trata se alguma das promises falhar | |
console.error('Failed retrieving information', err); | |
}); |
[UPDATE] Este trecho foi acrescentado após sugestão nos comentários.
Fetch de outros tipos/objetos
Mas também podemos recuperar o resultado da requisição lendo seus bytes, para por exemplo, carregar uma imagem, pdf, ou outro tipo de formato/blob. Para conseguirmos isto, precisamos acessar um reader
da resposta. Para isto, usamos o método getReader
vindo no body
da resposta.
let reader = response.body.getReader();
O interessante é que um objeto Response só pode ser manuseado por um único reader. Sendo assim, após manusea-lo, não é possível pegar outro reader.
O reader tem o método read
, que retorna uma promise:
reader.read().then(function(data){ // use o data });
Agora sim, podemos usar o conteúdo! Ou quase isto!
Esta Promise é resolvida com um objeto que tem o conteúdo retornado pela requisição em sua propriedade value
. Mas ela vem otimizada em Uint8Array
. Se quiser transformar este objeto em String, podemos usar o fromCharCode
do objeto String.
console.log(String.fromCharCode.apply(null, data.value));
Caso tenha alguma dificuldade com o método apply do objeto Function, leia meu artigo sobre call, bind e apply.
Em resumo, caso queira usar a resposta utilizando readers, use:
fetch(URL_TO_FETCH) | |
.then(function(response) { | |
response.body.getReader().read() | |
.then(function(data) { | |
// transformando em string, para visualizarmos melhor | |
let fetched = String.fromCharCode.apply(null, data.value); | |
console.log(fetched); | |
}); | |
}) | |
.catch(function(err) { | |
console.error('Failed retrieving information', err); | |
}); |
Fetch Options
Em nosso primeiro exemplo, passamos também um objeto com a propriedade method
. Este objeto é opcional, onde method será por padrão "get".
Mas este objeto nos permite passar alguns outros parâmetros.
fetch(URL_TO_FETCH, { | |
method: 'POST', | |
mode: 'cors', // pode ser cors ou basic(default) | |
redirect: 'follow', | |
headers: new Headers({ | |
'Content-Type': 'text/plain' | |
}) | |
}) | |
.then(function(response) { | |
// tratar a response | |
}); |
Podemos criar a requisição utilizando os métodos:
GET
POST
PUT
DELETE
HEAD
Você deve ter reparado no uso de new Headers
.
Headers
Instancias de Header podem ser passadas para o objeto Request (criado implicitamente pelo fetch), a fim de de possibilitar a manipulação das propriedades de header
da requisição.
// Podemos instanciar um Header já passando um objeto | |
// com as propriedades que queremos setar | |
let headers = new Headers({ | |
'Content-Type': 'text/plain', | |
'X-Custom-Header': 'valor' | |
}); | |
// mas também podemos adicionar programaticamente | |
// depois de já termos instanciado | |
headers.append('X-Custom-Header', 'valor'); | |
// além disso podemos checar, pegar ou setar valores | |
headers.get('Content-Type'); // "text/plain" | |
headers.set('Content-Type', 'application/json'); | |
headers.has('Content-Type'); // true | |
// assim como deletar propriedades de Header | |
headers.delete('X-Custom-Header'); |
Fetch por Post
Quando queremos enviar dados pelo método POST, podemos passar estas informações em um objeto na propriedade body
da requisição.
Caso queiramos passar os dados de um formulário pela requisição, podemos utilizar o objeto formData:
fetch(URL_TO_POST, { | |
method: 'post', | |
body: new FormData(document.querySelector('#my-form')) | |
}) | |
.then(function(response) { | |
// trate a resposta aqui | |
}); |
Conclusão
A Fetch API nos facilita muito o trabalho no dia-a-dia, e também formaliza e padroniza a forma como faremos requisições. Uma coisa importante também, é que a Fetch API é a base para outras tecnologias que estão surgindo e que serão abordadas em outros posts, como Cache API e Web Services.
Algumas fontes para leitura:
QUando foi lançada a fetch API?
Quando foi lançada a fetch API?