Pesquisa de site

javascript - Como faço para cancelar uma requisição HTTP fetch()?


Existe uma nova API para fazer requisições a partir do JavaScript: fetch(). Existe algum mecanismo incorporado para cancelar essas requisições em andamento?

Resposta #1

Resumo:

fetch agora suporta um parâmetro signal desde 20 de setembro de 2017, mas nem todos os navegadores parecem suportar isso no momento.

ATUALIZAÇÃO 2020: A maioria dos principais navegadores (Edge, Firefox, Chrome, Safari, Opera e alguns outros) suporta o recurso, que se tornou parte do padrão vivo do DOM. (em 5 de março de 2020)

Esta é uma mudança que veremos muito em breve, e portanto você deverá ser capaz de cancelar uma solicitação usando um AbortController com um AbortSignal.

Versão Longa

Como:

O jeito que funciona é assim:

Passo 1: Você cria um AbortController (Por enquanto eu apenas usei este)

const controller = new AbortController()

Passo 2: Você obtém o sinal do AbortController assim:

const signal = controller.signal

Passo 3: Você passa o signal para o fetch assim:

fetch(urlToFetch, {
    method: 'get',
    signal: signal, // <------ This is our AbortSignal
})

Passo 4: Basta abortar sempre que precisar:

controller.abort();

Aqui está um exemplo de como isso funcionaria (funciona no Firefox 57+):

// Create an instance.
const controller = new AbortController()
const signal = controller.signal

/*
// Register a listenr.
signal.addEventListener("abort", () => {
    console.log("aborted!")
})
*/


function beginFetching() {
  console.log('Now fetching');
  var urlToFetch = "https://httpbin.org/delay/3";

  fetch(urlToFetch, {
      method: 'get',
      signal: signal,
    })
    .then(function(response) {
      console.log(`Fetch complete. (Not aborted)`);
    }).catch(function(err) {
      console.error(` Err: ${err}`);
    });
}


function abortFetching() {
  console.log('Now aborting');
  // Abort.
  controller.abort()
}
<h1>Example of fetch abort</h1>
<hr>
<button onclick="beginFetching();">Begin</button>
<button onclick="abortFetching();">Abort</button>

Fontes:

  • A versão final do AbortController foi adicionada à especificação do DOM
  • O PR correspondente à especificação de fetch agora foi mesclado.
  • O rastreamento de bugs do navegador sobre a implementação do AbortController está disponível aqui: Firefox: #1378342, Chromium: #750599, WebKit: #174980, Edge: #13009916.

Resposta #2

https://developers.google.com/web/updates/2017/09/abortable-fetch

https://dom.spec.whatwg.org/#aborting-ongoing-activities

// setup AbortController
const controller = new AbortController();
// signal to pass to fetch
const signal = controller.signal;

// fetch as usual
fetch(url, { signal }).then(response => {
  ...
}).catch(e => {
  // catch the abort if you like
  if (e.name === 'AbortError') {
    ...
  }
});

// when you want to abort
controller.abort();

funciona no Edge 16 (17-10-2017), Firefox 57 (14-11-2017), Safari para desktop 11.1 (29-03-2018), Safari no iOS 11.4 (29-03-2018), Chrome 67 (29-05-2018) e posteriores.


em navegadores mais antigos, você pode usar o polyfill whatwg-fetch do GitHub e o polyfill AbortController. você também pode detectar navegadores mais antigos e usar os polyfills condicionalmente:

import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
import {fetch} from 'whatwg-fetch'

// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch

Artigos relacionados