AbortController는 1개 이상의 API 요청을 취소할 때 사용하는 인터페이스다. 주로 중복 요청이 있을 때 이전 요청을 취소할 때 사용하며, 비동기 작업을 다룰 때도 활용할 수 있다. Axios 0.22 버전부터 AbortController를 이용해서 API 요청을 취소할 수 있다. Cancel 토큰을 이용하는 방식은 deprecated 됐다.

기본 사용 방법


AbortController는 아래 3가지 단계로 사용한다. abortController.abort() 메서드를 호출하면 abort 이벤트가 발생하며 fetch 프로미스는 rejected 상태가 되고 제어는 catch 블럭으로 진입한다.

  1. AbortController 인스턴스 생성
  2. 인스턴스의 signal 프로퍼티를 fetchsignal 옵션에 할당 — AbortSignal 인스턴스 등록
  3. abortController.abort 메서드 호출해서 요청 취소 — abort 이벤트 호출

<aside> 💡 abortController로 인한 요청 취소 판별 방법 3가지

  1. catch 메서드에서 Error 객체의 name 프로퍼티가 아래와 같을 때
    1. fetch : "AbortError"
    2. axios: "CanceledError"
  2. catch 메서드에서 abortController.signal.aborted 값이 true 일 때
  3. (axios) axios.isCancel(event) 반환값이 true일 때 </aside>
const abortController = new AbortController(); // ⑴ AbortController 인스턴스 생성

// axios.get('...', { signal: abortController.signal })
fetch('<https://random-data-api.com/api/v2/users>', {
  signal: abortController.signal, // ⑵ AbortSignal 인스턴스 등록
})
  .then(console.log) // 요청을 취소했으므로 건너뜀
  .catch(e => console.log(e.name)); // "AbortError"

abortController.abort('abort test'); // ⑶ abort 이벤트 호출 (API 요쳥 취소)

요청 취소 화면 — 네트워크 탭

요청 취소 화면 — 네트워크 탭

요청을 취소하면 signal 프로퍼티의 aborted 속성이 true로 바뀌어 있는걸 확인할 수 있다. reason 속성엔 abort() 메서드를 호출했을 때 인자로 넘긴 텍스트 메시지가 담겨있다.

Untitled

AbortSignal


AbortController.signal 프로퍼티는 DOM 요청과 통신하거나 취소할 때 사용하는 AbortSignal의 인스턴스다(읽기 전용). signal 프로퍼티는 abort() 메서드의 호출 여부를 나타내는 aborted 속성을 가진다. abort 이벤트에 리스너를 등록할 때도 signal 프로퍼티를 이용한다.

const controller = new AbortController(); // AbortController 인스턴스 생성
const signal = controller.signal; // AbortSignal 인스턴스 반환

// signal 객체에 abort 이벤트 핸들러 등록
signal.addEventListener('abort', () => console.log("abort 이벤트 발생!"));
controller.abort(); // abort 이벤트 발생!

console.log(signal.aborted); // true

AbortController.signal 프로퍼티를 이용해 다운로드 작업을 수동으로 취소하도록 할 수도 있다.

const controller = new AbortController();
const { signal } = controller;

const $downloadBtn = document.querySelector('.download'); // 다운로드 시작 버튼
const $abortBtn = document.querySelector('.abort'); // 다운로드 취소 버튼
const $reports = document.querySelector('.reports'); // 에러 메시지 표시 요소

$downloadBtn.addEventListener('click', fetchVideo); // 클릭시 fetchVideo 요청 시작

$abortBtn.addEventListener('click', () => {
  controller.abort(); // fetchVideo 요청 취소
  console.log('Download aborted');
});

function fetchVideo() {
  fetch('url', { signal })
    .then(response => {
      // ...
    })
    .catch(e => {
      $reports.textContent = 'Download error: ' + e.message;
    });
}

Abort APi example

위 예제 코드의 샘플 사이트