jiho_bae
Go devlog
jiho_bae
전체 방문자
오늘
어제
  • 분류 전체보기 (158)
    • JavaScript (38)
      • theory (34)
      • vanilla (4)
    • HTML & CSS (2)
    • Browser (3)
    • CS (6)
      • linux (1)
      • shell (2)
      • compiler (2)
    • DS & Algorithm (87)
      • theory (5)
      • basic (7)
      • programmers (30)
      • baekjoon (45)
    • Design Pattern (2)
    • Error (4)
    • Git & Github (4)
    • Tools (1)
    • 부트캠프 (4)
    • Small Tips (2)
    • Java (3)
    • test (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 자바스크립트 채팅방 스크롤
  • javascript use strict
  • 외벽 점검 javascript
  • 자바스크립트 sort는 왜 그모양일까
  • 1753 최단경로 javascript
  • 13460 javascript nodejs
  • fetch 취소하기
  • 프로그래머스 숫자카드나누기 javascript
  • 자바스크립트 배열의 특수함
  • 덧칠하기 javascript
  • 자바스크립트 비동기 마이크로 태스크 큐와 렌더링 과정
  • 병합정렬 자바스크립트
  • 카카오 코딩테스트 양궁대회 nodeJS
  • 백준 자바스크립트 입력 템플릿
  • 자바스크립트 이벤트 위임
  • 계수정렬 자바스크립트
  • 리코쳇 로봇 javascript
  • 리액트 프로젝트 디버깅하기
  • 자바스크립트 커링
  • 자바스크립트 모듈 시스템
  • 백준 17406 nodeJS
  • safari Date format NaN
  • 대충만든자판 javascript
  • 퀵정렬 자바스크립트
  • JavaScript
  • safari invalid date error
  • 25632 소수 부르기 게임
  • 가사 검색 자바스크립트
  • 깃 이전 커밋에서 새 브랜치 만들기
  • 억억단을 외우자 javascript

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
jiho_bae
Browser

비동기 작업 취소하기. "AbortController"

비동기 작업 취소하기. "AbortController"
Browser

비동기 작업 취소하기. "AbortController"

2022. 7. 24. 20:25

예전에 과제전형 테스트에서 "비동기 요청 *초 전까지 응답이 오지 않는다면,

요청 취소 후 재전송"이라는 요구사항이 있었는데

그 이후(시원하게 말아먹고 난 이후) AbortController의 존재에 대해서 알게 되었다. 👍👍

 

먼저 간단하게 비동기 요청시 사용되는 fetch API의 특징을 간단하게 알아보고,

포스팅의 주 대상 AbortController를 공부해보자.


fetch : return Promise

fetch API의 결과는 Promise이다.

응답이 오기 전 까지 pending(대기) 상태를 유지하게 되며,

pending 상태가 끝나면 fullfilled 혹은 rejected로 바뀌게 된다.

 

fetch 자체만으로는 pending을 취소하는 방법이 따로 존재하지 않으며,

여기서 pending 상태는 "요청하고 응답을 기다리는중" 이므로, 어쩌면 응답을 무한정 기다려야 될 수도 있다.

 


AbortController?

Abort = (도중에) 중단시키다.

웹 요청 취소를 지원하는 객체이다.

 

new 키워드와 함께 호출하여 생성자로 AbortContoller를 생성하여, 비동기 작업시 이용할 수 있다.

알아야 할 프로퍼티는 2가지다. signal, abort!

 

AbortController.signal

signal은 읽기전용 프로퍼티로, fetch 요청 전송시 옵션으로 함께 넣어주게 된다.

fetch api에서 signal 옵션으로 넣어줌으로서, XHR 객체(요청)와 생성한 AbortController 인스턴스가 통신할 수 있게 된다.

 

AbortController.abort()

abort 메서드를 호출하면 요청 완료전에 취소할 수 있다.

abort 메서드가 signal 객체의 내부 상태를 바꿔준다.

 

요약하면 AbortController 인스턴스를 생성하고, signal로 신호,컨트롤러와 요청간 연결 후 abort 메서드로 취소할 수 있다.

abort()에 의해 signal 객체의 상태가 바뀌게 된다.


사용 예시

app.get('/abort', (req, res) => {
  const targetNumber = Math.random();
  let randomNumber = Math.random();
  let cntOfFailure = 0;

  while (targetNumber !== randomNumber) {
    if (cntOfFailure > 1e8 * 5) res.send('fail');

    randomNumber = Math.random();
    cntOfFailure++;
  }

  res.send('success');
});

간단하게 5억번의 기회 안에 랜덤 소수를 맞추면 "success" 응답을 주는 endpoint를 만들어보았다.

 

어차피 못맞출거다. 혹시 "success"를 받았다면 무척 운이 좋은 것이니, 당장 로또사러..

아무튼 해당 요청은 최소 1번에서 최대 5억번의 while문이 돌아가야 하기 때문에 "꽤 오래걸릴 예정이다."

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
  </head>
  <body>
    <button onClick="request()">요청하기</button>
    <button onClick="cancel()">요청 취소하기</button>
    <p id="status"></p>
    <script>
      const status = document.querySelector('#status');
      let abort = new AbortController();

      async function request() {
        try {
          status.innerHTML = '요청중....';
          const res = await fetch('--요청이 오래걸릴 수 있는 url--', {
            signal: abort.signal,
          });
          status.innerHTML = `요청에 대한 응답이 도착하였습니다!!.`;
        } catch (err) {
          status.innerHTML = `에러 로그 : ${err}`;
        }
      }

      function cancel() {
        status.innerHTML = '요청 취소!';
        abort.abort();
      }
    </script>
  </body>
</html>

그리고 간단하게 html파일로 테스트 해보자.

- 요청하기 버튼을 누르면 "요청중..." 메시지를 보여준다.

- fetch option에 signal을 포함하여 비동기요청을 보낸다.

- 응답이 오면 "요청에 대한 응답이 도착하였습니다!!" 메시지를 보여준다.

- 응답이 오기 전에 요청 취소하기 버튼을 누르면, "요청 취소!" 메시지를 보여준다.

- 에러 발생시에는 "에러로그 : error message" 메시지를 보여준다.

 

요청 후 응답을 기다리는 모습

 

요청 후 abort() 메서드로 취소한 모습

 

요청이 잘 동작하는 모습이다.

 

abort.signal.addEventListener('abort', () => alert('취소'));

signal 객체에는 이벤트리스너도 달아줄 수 있다.

"abort" 이벤트 발생시, 콜백을 실행하게 되고, alert을 띄워주도록 동작시켜봤다.

 

signal의 이벤트리스너 콜백이 잘 동작한다.

 

마지막으로 너무 오래 기다리다가 결국 취소한 요청을 다시 전송하고 싶을 수 있다.

이 경우를 다뤄보자.


요청 취소 후 재요청하기.

아마 취소 후에 "요청하기"버튼을 다시 누르면 요청을 수행할 것 같다.

그런데 생각과는 다르게, 다시 요청이 전송되지 않는다.

 

AbortError: Failed to execute 'fetch' on 'Window': The user aborted a request.

AbortController.signal.aborted 값이 true이기 때문이다.

 

그럼 AbortController를 재생성해주면 되겠다.

async function request() {
        try {
          abort = new AbortController();
          status.innerHTML = '요청중....';
          ...
          }
}

간단하게 request 함수 실행시 객체를 만들어주자.

 

이제 취소 후에 새롭게 AbortController 객체를 생성한 뒤 재요청을 시도한다.

 

 

 

MDN 한국번역본에서는 Experimental이라고 해서, 영어로 바꿔보니 Experimental 문구는 사라졌다.

https://developer.mozilla.org/en-US/docs/Web/API/AbortController 

https://developer.mozilla.org/ko/docs/Web/API/AbortController

IE 빼고 모두 지원하고 있다.


참고

https://developer.mozilla.org/en-US/docs/Web/API/AbortController 

 

 

저작자표시 (새창열림)

'Browser' 카테고리의 다른 글

[CORS] 다른 출처간 CORS 에러 해결과 웹팩 개발 서버의 Proxy 설정  (1) 2021.11.15
웹 크롤링과 웹 크롤러 봇  (0) 2021.11.14
  • fetch : return Promise
  • AbortController?
  • 사용 예시
  • 요청 취소 후 재요청하기.
  • 참고
'Browser' 카테고리의 다른 글
  • [CORS] 다른 출처간 CORS 에러 해결과 웹팩 개발 서버의 Proxy 설정
  • 웹 크롤링과 웹 크롤러 봇
jiho_bae
jiho_bae
하루에 한 걸음씩

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.