Programing

HTTP fetch () 요청을 어떻게 취소합니까?

crosscheck 2020. 6. 4. 18:57
반응형

HTTP fetch () 요청을 어떻게 취소합니까?


JavaScript에서 요청을 작성하기위한 새로운 API 인 fetch ()가 있습니다. 기내에서 이러한 요청을 취소 할 수있는 메커니즘이 있습니까?


TL / DR :

fetchsignal2017 년 9 월 20 일 현재 매개 변수를 지원 하지만 모든 브라우저 가이 atm을 지원하는 것은 아닙니다 .

이것은 곧 변경 될 예정이므로 AbortControllers 를 사용하여 요청을 취소 할 수 있습니다 AbortSignal.

긴 버전

어떻게:

작동 방식은 다음과 같습니다.

1 단계 : 당신은 AbortController(지금은 방금 이것을 사용 했습니다 )

const controller = new AbortController()

2 단계 : 다음 AbortController과 같이 s 신호를 얻습니다 .

const signal = controller.signal

3 단계 : 다음 signal과 같이 페치를 전달합니다 .

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

4 단계 : 필요할 때마다 중단하십시오.

controller.abort();

작동 방식의 예는 다음과 같습니다 (Firefox 57 이상에서 작동).

<script>
    // 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()
    }

</script>



<h1>Example of fetch abort</h1>
<hr>
<button onclick="beginFetching();">
    Begin
</button>
<button onclick="abortFetching();">
    Abort
</button>

출처 :

  • AbortController 의 최종 버전이 DOM 사양에 추가되었습니다
  • 해당 PR 페치 사양 지금 병합됩니다.
  • AbortController의 구현을 추적하는 브라우저 버그는 여기에서 제공됩니다 : Firefox : # 1378342 , Chromium : # 750599 , WebKit : # 174980 , Edge : # 13009916 .

기존 가져 오기 API로 요청을 취소하는 방법이 없다고 생각합니다. https://github.com/whatwg/fetch/issues/27 에서 이에 대한 토론이 진행 중입니다.

Update May 2017: Still no resolution. Requests cannot be canceled. More discussion at https://github.com/whatwg/fetch/issues/447


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();

works in edge 16 (2017-10-17), firefox 57 (2017-11-14), desktop safari 11.1 (2018-03-29), ios safari 11.4 (2018-03-29), chrome 67 (2018-05-29), and later.


on older browsers, you can use github's whatwg-fetch polyfill and AbortController polyfill. you can detect older browsers and use the polyfills conditionally, too:

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

As of Feb 2018, fetch() can be cancelled with the code below on Chrome (read Using Readable Streams to enable Firefox support). No error is thrown for catch() to pick up, and this is a temporary solution until AbortController is fully adopted.

fetch('YOUR_CUSTOM_URL')
.then(response => {
  if (!response.body) {
    console.warn("ReadableStream is not yet supported in this browser.  See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream")
    return response;
  }

  // get reference to ReadableStream so we can cancel/abort this fetch request.
  const responseReader = response.body.getReader();
  startAbortSimulation(responseReader);

  // Return a new Response object that implements a custom reader.
  return new Response(new ReadableStream(new ReadableStreamConfig(responseReader)));
})
.then(response => response.blob())
.then(data => console.log('Download ended. Bytes downloaded:', data.size))
.catch(error => console.error('Error during fetch()', error))


// Here's an example of how to abort request once fetch() starts
function startAbortSimulation(responseReader) {
  // abort fetch() after 50ms
  setTimeout(function() {
    console.log('aborting fetch()...');
    responseReader.cancel()
    .then(function() {
      console.log('fetch() aborted');
    })
  },50)
}


// ReadableStream constructor requires custom implementation of start() method
function ReadableStreamConfig(reader) {
  return {
    start(controller) {
      read();
      function read() {
        reader.read().then(({done,value}) => {
          if (done) {
            controller.close();
            return;
          }
          controller.enqueue(value);
          read();
        })
      }
    }
  }
}

As for now there is no proper solution, as @spro says.

However, if you have an in-flight response and are using ReadableStream, you can close the stream to cancel the request.

fetch('http://example.com').then((res) => {
  const reader = res.body.getReader();

  /*
   * Your code for reading streams goes here
   */

  // To abort/cancel HTTP request...
  reader.cancel();
});

참고URL : https://stackoverflow.com/questions/31061838/how-do-i-cancel-an-http-fetch-request

반응형