fetch()
permite fazer solicitações de rede semelhantes a XMLHttpRequest (XHR). A
principal diferença é que a API Fetch usa promessas, que têm uma
API mais simples para ajudar a evitar os callbacks complicados na
API XMLHttpRequest.
Se você nunca usou promessas antes, confira Introdução às promessas do JavaScript.
Solicitação de busca básica
Confira um exemplo implementado com um XMLHttpRequest
e depois com fetch
. Queremos solicitar um URL, receber uma resposta e analisar
como JSON.
XMLHttpRequest
Um XMLHttpRequest
precisa de dois listeners para processar os casos
de sucesso e de erro, além de uma chamada para open()
e send()
.
Exemplo das documentações do MDN.
function reqListener () {
const data = JSON.parse(this.responseText);
console.log(data);
}
function reqError (err) {
console.log('Fetch Error :-S', err);
}
const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
Buscar
Nossa solicitação de busca tem esta aparência:
fetch('./api/some.json')
.then(response => {
if (response.status !== 200) {
console.log(`Looks like there was a problem. Status Code: ${response.status}`);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
})
.catch(err => {
console.log('Fetch Error :-S', err);
});
A solicitação fetch()
precisa de apenas uma chamada para fazer o mesmo trabalho do exemplo de XHR. Para processar a resposta, primeiro verificamos se o status dela é
200 e, em seguida, analisamos a resposta como JSON. A resposta a uma solicitação fetch()
é um objeto Stream, o que significa que, depois de chamarmos o método json()
, uma promessa é retornada.
O stream ocorre de forma assíncrona.
Metadados de resposta
O exemplo anterior mostrou o status do objeto Response e como analisar a resposta como JSON. Confira como processar outros metadados que talvez você queira acessar, como cabeçalhos:
fetch('users.json').then(response => {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
Tipos de resposta
Quando fizermos uma solicitação de busca, a resposta receberá um response.type
de "basic
",
"cors
" ou
"opaque
".
Esses types
mostram de onde veio o recurso, e é possível usá-los para
determinar como tratar o objeto de resposta.
Quando o navegador solicita um recurso na mesma origem, a resposta tem um
tipo basic
com restrições sobre o que pode ser visualizado.
Se uma solicitação for feita para um recurso em outra origem e essa origem retornar
cabeçalhos CORS, o tipo será cors
. As respostas cors
são semelhantes às respostas basic
, mas restringem os cabeçalhos que
podem ser visualizados a Cache-Control
, Content-Language
, Content-Type
, Expires
,
Last-Modified
e Pragma
.
As respostas opaque
vêm de uma origem diferente que não retorna cabeçalhos CORS. Com uma resposta opaca, não será possível ler os dados retornados nem visualizar o status da solicitação, o que significa que não é possível verificar se a solicitação foi bem-sucedida.
É possível definir um modo para uma solicitação de busca para que apenas determinados tipos de solicitação sejam resolvidos. Os modos que podem ser definidos são:
- O
same-origin
só é bem-sucedido para solicitações de recursos na mesma origem e rejeita todas as outras. cors
permite solicitações de recursos da mesma origem e outras que retornem os cabeçalhos de CORs apropriados.- O
cors-with-forced-preflight
executa uma verificação pré-voo antes de fazer qualquer solicitação. - O
no-cors
tem como objetivo fazer solicitações para outras origens que não têm cabeçalhos CORS e resultar em uma respostaopaque
, mas, conforme declarado, isso não é possível no escopo global da janela no momento.
Para definir o modo, adicione um objeto de opções como o segundo parâmetro na
solicitação fetch
e defina o modo nesse objeto:
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(response => response.text())
.then(text => {
console.log('Request successful', text);
})
.catch(error => {
log('Request failed', error)
});
Encadeamento de promessas
Um dos melhores recursos das promessas é a capacidade de encadeá-las. Para
fetch()
, isso permite compartilhar a lógica entre as solicitações de busca.
Se você estiver trabalhando com uma API JSON, será necessário verificar o status e analisar o JSON para cada resposta. Simplifique seu código definindo o status e a análise de JSON em funções separadas que retornam promessas e use a solicitação de busca para lidar apenas com os dados finais e o caso de erro.
function status (response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json (response) {
return response.json()
}
fetch('users.json')
.then(status)
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
}).catch(error => {
console.log('Request failed', error);
});
Este exemplo define uma função status
que verifica a response.status
e
retorna uma promessa resolvida como
Promise.resolve()
ou uma promessa rejeitada como
Promise.reject()
.
Esse é o primeiro método chamado na cadeia fetch()
.
Se a promessa for resolvida, o script vai chamar o método json()
, que
retorna uma segunda promessa da chamada response.json()
e cria um
objeto que contém o JSON analisado. Se a análise falhar, a promessa será
rejeitada e a instrução "catch" será executada.
Essa estrutura permite compartilhar a lógica em todas as suas solicitações de busca, facilitando a manutenção, a leitura e o teste do código.
Solicitação POST
Às vezes, um app da Web precisa chamar uma API com um método POST e incluir alguns
parâmetros no corpo da solicitação. Para fazer isso, defina os parâmetros method
e body
nas opções fetch()
:
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(error => {
console.log('Request failed', error);
});
Enviar credenciais com uma solicitação de busca
Para fazer uma solicitação de busca com credenciais, como cookies, defina o valor de credentials
da solicitação como "include"
:
fetch(url, {
credentials: 'include'
})