Introdução a fetch()

fetch() permite fazer solicitações de rede semelhantes a XMLHttpRequest (XHR). A a principal diferença é que a API Fetch usa promessas, que têm um API mais simples para ajudar a evitar callbacks complicados no API XMLHttpRequest.

Compatibilidade com navegadores

  • Chrome: 42.
  • Borda: 14.
  • Firefox: 39.
  • Safari: 10.1.

Origem

Se você nunca usou Promessas confira a Introdução às promessas do JavaScript (em inglês).

Solicitação de busca básica

Confira um exemplo implementado com uma XMLHttpRequest e depois fetch. Queremos solicitar um URL, receber uma resposta e analisar como JSON.

XMLHttpRequest

Um XMLHttpRequest precisa de dois listeners para processar o sucesso. e casos de erro, além de uma chamada para open() e send(). Exemplo de documentos da 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();

Fetch

A solicitação de busca tem esta aparência:

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 de apenas uma chamada para fazer o mesmo trabalho que o XHR exemplo. Para processar a resposta, primeiro verificamos se o status dela é 200 e analise a resposta como JSON. A resposta a uma solicitação fetch() é uma Stream, o que significa que, após chamamos o método json(), uma promessa é retornada. O stream ocorre de forma assíncrona.

Metadados de resposta

O exemplo anterior mostrou o status da Response, e como e analisar a resposta como JSON. Veja como lidar com outros metadados que você pode querer 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 fizermos uma solicitação de busca, a resposta receberá um response.type de "basic", cors ou "opaque". Estes types mostram de onde veio o 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 pode ser visualizado na resposta.

Se for feita uma solicitação para um recurso em outra origem e essa origem retornar cabeçalhos CORs, o tipo será cors. cors as respostas são semelhantes às respostas basic, mas restringem os cabeçalhos que você pode visualizar até Cache-Control, Content-Language, Content-Type, Expires, Last-Modified e Pragma.

As respostas de opaque vêm de uma origem diferente que não retorna CORS e cabeçalhos de cache válidos. Com uma resposta opaca, não será possível ler os dados retornados ou conferir o status da solicitação, ou seja, você não pode conferir se a solicitação foi bem-sucedida.

É possível definir um modo para uma solicitação de busca de modo que apenas determinados tipos de solicitação resolver. Os modos que podem ser definidos são:

  • same-origin só funciona para solicitações de recursos na mesma origem. rejeita todas as outras solicitações.
  • cors permite solicitações de recursos na mesma origem e em outras origens que retornar os cabeçalhos CORs apropriados.
  • O cors-with-forced-preflight executa uma simulação de verificação antes de fazer qualquer solicitação.
  • O objetivo de no-cors é fazer solicitações a outras origens que não têm CORS cabeçalhos e resultam em uma resposta opaque, mas, como informado, 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 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(), que permite compartilhar a lógica entre solicitações de busca.

Se estiver trabalhando com uma API JSON, é necessário verificar o status e analisar o JSON para cada resposta. É possível simplificar seu código definindo o status e A análise JSON em funções separadas que retornam promessas e usa o método de busca para manipular apenas 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(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

Esse exemplo define uma função status que verifica response.status e retorna uma promessa resolvida Promise.resolve(), ou uma promessa rejeitada Promise.reject(). Esse é o primeiro método chamado na cadeia fetch().

Se a promessa for resolvida, o script chamará o método json(), que retorna uma segunda promessa da chamada response.json() e cria uma que contém o JSON analisado. Se a análise falhar, a promessa será será rejeitada e a declaração de captura será executada.

Essa estrutura permite que você compartilhe a lógica em todas as solicitações de busca, tornando código mais fácil de manter, ler e testar.

Solicitação POST

Às vezes, um app da Web precisa chamar uma API com um método POST e incluir alguns no corpo da solicitação. Para fazer isso, defina 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 método Valor de credentials para "include":

fetch(url, {
    credentials: 'include'
})