fetch()
permite fazer solicitações de rede semelhantes a XMLHttpRequest (XHR). A
principal diferença é que a API Fetch usa promessas, que tem uma
API mais simples para ajudar a evitar os callbacks complicados na
API XMLHttpRequest.
Caso você nunca tenha usado promessas em JavaScript, confira a Introdução às promessas do JavaScript.
Solicitação básica de busca
Veja um exemplo implementado com XMLHttpRequest
e depois com fetch
. Queremos solicitar um URL, receber uma resposta e analisá-lo 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 de documentos do MDN
function reqListener() {
var data = JSON.parse(this.responseText);
console.log(data);
}
function reqError(err) {
console.log('Fetch Error :-S', err);
}
var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
Busca
Nossa solicitação de busca é semelhante a esta:
fetch('./api/some.json')
.then(
function(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(function(err) {
console.log('Fetch Error :-S', err);
});
A solicitação fetch()
precisa apenas de uma chamada para fazer o mesmo trabalho que o exemplo
XHR. Para processar a resposta, primeiro verificamos se o status é
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 chamar 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. Veja como processar outros metadados que talvez você queira acessar, como cabeçalhos:
fetch('users.json').then(function(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 fazemos uma solicitação de busca, a resposta recebe um response.type
de "basic
",
"cors
" ou
"opaque
".
Esses types
mostram a origem do recurso e podem ser usados 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 você pode ver na resposta.
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 você pode ver para 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 é possível ler os dados retornados nem ver o status da solicitação, o que significa que não é possível verificar se ela foi bem-sucedida.
É possível definir um modo para uma solicitação de busca, de modo que apenas determinados tipos de solicitação sejam resolvidos. Os modos que podem ser configurados são os seguintes:
same-origin
só é bem-sucedido para solicitações de recursos na mesma origem e rejeita todas as outras solicitações.cors
permite solicitações de recursos na mesma origem e em outras origens que retornam os cabeçalhos CORs apropriados.cors-with-forced-preflight
executa uma verificação de simulação antes de fazer qualquer solicitação.no-cors
destina-se a 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(function(response) {
return response.text();
})
.then(function(text) {
console.log('Request successful', text);
})
.catch(function(error) {
log('Request failed', error)
});
Encadeamento de promessas
Um dos melhores recursos das promessas é a capacidade de encadeá-las. Para
fetch()
, isso permite compartilhar lógica entre 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. É possível simplificar o código definindo o status e a análise JSON em funções separadas que retornam promessas e use a solicitação de busca para processar apenas os dados finais e o caso do 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(function(data) {
console.log('Request succeeded with JSON response', data);
}).catch(function(error) {
console.log('Request failed', error);
});
Neste exemplo, definimos 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 contendo o JSON analisado. Se a análise falhar, a promessa será
rejeitada e a instrução de captura será executada.
Essa estrutura permite compartilhar a lógica em todas as 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(function (data) {
console.log('Request succeeded with JSON response', data);
})
.catch(function (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 credentials
da solicitação como "include"
:
fetch(url, {
credentials: 'include'
})