Usando o Fetch API ao invés do jQuery.Ajax

Segundo o site buildwith o jQuery ainda é utilizado por cerca de 78.2% dos principais sites na internet. Sim. 78% dos sites ainda usam de alguma forma o icônico $.

Atualmente com seus aproximadamente 86K na versão 2.2.2, o jQuery possui uma série de recursos importantes para nosso dia-a-dia como desenvolvedores front-end. Com o passar do tempo os browsers foram se atualizando, e a cada dia vemos a não necessidade de adicionar o jQuery em nossos projetos.

Por incrível que possa parecer, muita gente ainda adiciona o jQuery inteiro no projeto simplesmente por causa do jQuery.ajax. Nesse post vamos conhecer a Fetch API, talvez este seja o motivo que você estava procurando para abandonar de vez o jQuery.

Segundo o site caniuse a Fetch API está presente em aproximadamente 55% dos navegadores do mundo. Isso significa que para utilizarmos em nossos projetos vamos precisar de um Polyfill. É só seguir as instruções de instalação descritas no repositório ou utilizar diretamente do cdnjs.

A Fetch API utiliza Promises. Se você nunca utilizou Promises no seu desenvolvimento, dê uma lida nesse ótimo artigo do Jake Archibald antes de continuar.

Utilização Básica

Se você estiver em uma versão de browser compatível ou estiver utilizando o polyfill o objeto window agora possui um método chamado fetch.

fetch('/some/url', { method: 'get' })  
   .then(function (response) { })
   .catch(function (err) { // Error });

A assinatura do método é fetch(request[, options]) onde request pode ser uma String ou uma instância da classe Request e options sendo um parâmetro opcional que quando declarado deve ser um Object contendo os seguintes parâmetros:

  • method
    • O método do request. GET, POST, etc.
  • headers
    • Headers que você deseja enviar no request.
  • body
  • mode
    • Modo do request. cors, no-cors ou same-origin.
  • credentials
    • Se o request deve incluir os cookies para o domínio atual. omit, same-origin ou include.
  • cache
    • O modo de cache. default, no-store, no-cache, force-cache ou only-if.
  • redirect
    • O modo de redirect. follow, error ou manual.
  • referrer
    • no-referer, client ou uma URL.

Todas as chamadas para o método fetch retornam uma Promise que são resolvidas com uma Response.

Utilizando a classe Request

Ao invés de usar uma String é possível passar uma instância da classe Request como o primeiro parâmetro do método fetch.

fetch(new Request('/users.json', {  
  method: 'POST', 
  mode: 'cors', 
  redirect: 'follow',
  headers: new Headers({
    'Content-Type': 'text/plain'
  })
})).then(function(response) { });

Com isso não é necessário passar o parâmetro options já que todas as opções presentes no objeto options são atributos da instância da classe Request.

Uma vez criada a instância de Request, todos seus parâmetros são read-only, ou seja, não podem ser modificados fora da construção da instância.

Um ponto importante sobre a instância da classe Request é que após ser criada ela só pode ser utilizada uma única vez pelo método fetch. Caso você queira refazer um determinado request utilizando as configurações de uma instância previamente criada basta utilizar o método clone presente na classe Request para efetuar uma nova chamada fetch.

Veja um exemplo abaixo:

var req = new Request('/users.json', {  
  method: 'POST', 
  mode: 'cors', 
  redirect: 'follow',
  headers: new Headers({
    'Content-Type': 'text/plain'
  })
});

var handleFailure = function () {  
  if (shouldRetry()) {
    fetch(req.clone()).then(handleSuccess);
  }
};

fetch(req).then(handleSuccess).catch(handleFailure)  

O objeto Response.

Toda Promise retornada pelo método fetch é resolvida com uma instância de Response – Abaixo vemos um exemplo onde fazemos um request para um arquivo JSON e transformamos o objeto Response em um JSON.

fetch('file.json')  
  .then(function (response) { 
    // Converte a resposta para um JSON
    return response.json();
  })
  .then(function(json) {
    console.log(json); 
  });

Além do método .json() uma instância de Response pode ser convertida para .text(), .blob(), .arrayBuffer() ou .formData(). A instância também possui atributos:

  • type
  • url
  • status
  • ok
  • statusText
  • headers

Como fazer um POST

É comum enviar dados para o backend utilizando POST ou PUT — Abaixo está um exemplo de como enviar dados para backend utilizando a Fetch API.

fetch('/post', {  
  method: 'post',
  body: JSON.stringify({
    email: '[email protected]',    
    password: '******'
  })
});

Upload de arquivos?

var input = document.querySelector('input[type="file"]')

var data = new FormData()  
data.append('file', input.files[0])

fetch('/upload', {  
  method: 'post',
  body: data
});

Not always a bed of roses. Sim, existem problemas funcionalidades não implementadas.

Como a Fetch API é relativamente nova, existem recursos presentes no XMLHttpRequest que ainda não foram incorporados na Fetch API. Muitos dos problemas já estão endereçados no repositório GitHub do projeto.

Não é possível cancelar um request.

Utilizando o jQuery.ajax é algo bem trivial.

var xhr = $.ajax({  
  type: "POST",
  url: "some.php",
  data: "name=John&location=Boston",
  success: function(msg){
    alert("Data Saved: " + msg);
  }
});

xhr.abort();  

Já existe uma discussão aberta no GitHub sobre qual deveria ser a melhor forma de fazer algo parecido com a Fetch API.

Não é possível acompanhar o progresso da requisição.

$.ajax({
  xhr: function() {
    var xhr = new window.XMLHttpRequest();
    xhr.upload.addEventListener("progress", ... );
  }
});

Existe a intenção de incluir a Stream API para que isso seja possível.

Finalizando

Talvez você não esteja disposto a abrir mão do jQuery no momento. Tudo bem. Não tem problema. Porém é interessante ver como os browsers estão se atualizando trazendo APIs simples que fornecem exatamente as mesmas algumas funcionalidades que o jQuery tem há algum tempo. Até mais.

Artigo do engenheiro de software do site VivaReal William Lepinski