가져오기 요청 중단

바닐라 JavaScriptfetch() API로 작업할 때 요청을 중단하는 것이 너무 직관적이지 않습니다.

요청을 중단해야 하는 이유는 무엇입니까?



중단 가능한 요청이 필요한 특정 사용 사례 중 하나는 React 구성 요소 내부였습니다. 구성 요소는 마운트 시 일부 데이터를 가져오고 가져온 데이터를 구성 요소의 내부 상태에 설정합니다.

가져오기는 비동기 작업이므로 가져오기 요청이 해결되기 전에 구성 요소가 마운트 해제될 수 있습니다. 따라서 React 구성 요소 내부에서 useEffect 후크로 작업하는 경우 요청을 중단하는 정리 기능을 제공해야 합니다.

가져오기 요청을 중단하는 방법



가져오기 요청과 함께 AbortController를 만들고 가져오기 옵션에서 신호 속성을 전달합니다.

const { signal } = new AbortController();
const response = await fetch('https://yesno.wtf/api', {signal});
const data = await response.json();
// do something with data


정리 기능에서 signal.abort(); 를 통해 중단 기능을 호출할 수 있습니다.

포장하기



내 프로젝트의 경우 가져오기 래퍼 클래스에서 모든 것을 래핑했습니다. 내 프로젝트에서 TypeScript를 사용하고 있으며 특정 사용 사례에 대한 몇 가지 결정을 내렸습니다.

json 데이터만 필요했기 때문에 하드코딩response.json()했습니다 💁‍♀️. 또한 응답이 2xx 정상이 아닌 경우 예외를 throw합니다.

/**
 * Exceptions from the API
 */
export interface ApiException {
  status: number;
  details: any; 
}

/**
 * Request State
 */
export enum RequestState {
  IDLE = 'idle',
  ABORTED = 'aborted',
  PENDING = 'pending',
  READY = 'ready',
  ERROR = 'error'
}

/**
 * Ajax class
 * 
 * Wrapper class around the fetch API. 
 * It creates an AbortController alongside with the request.
 * Also, it keeps track of the request state and throws an ApiException on HTTP status code !== 2xx
 * 
 */
export class Ajax<T = any> {

  promise: Promise<Response> | null;
  abortController: AbortController | null;

  info: RequestInfo;
  init: RequestInit;

  state: RequestState;

  /**
   * Ajax constructor. Takes the same arguments as fetch()
   * @param info 
   * @param init 
   */
  constructor(info: RequestInfo, init?: RequestInit) {
    this.abortController = new AbortController();
    this.init = { ...(init || {}), signal: this.abortController.signal };
    this.info = info;
    this.state = RequestState.IDLE;
    this.promise = null;
  }

  /**
   * Send API request. 
   * 
   * @returns {any} json data (await (await fetch()).json())
   * @throws {ApiException} exception if http response status code is not 2xx
   * 
   */
  async send(): Promise<T> {
    this.state = RequestState.PENDING;
    try {
      this.promise = fetch(this.info, this.init);
      const response = await this.promise;
      const json = await response.json();
      if (! response.ok) {
        throw {status: response.status, details: json} as ApiException;
      }
      this.state  = RequestState.READY;
      return json;
    } catch (ex) {
      this.state = RequestState.ERROR;
      throw ex;
    } finally {
      this.abortController = null;
    }
  }

  /**
   * Cancel the request.
   */
  abort(): void {
    if (this.abortController) {
      this.state = RequestState.ABORTED;
      this.abortController.abort();
      this.abortController = null;
    }
  }
}



용법:

const request = new Ajax('https://yesno.wtf/api');
const data = await request.send();

// abort it via:
request.abort();


그것이 정말로 삶을 더 쉽게 만들어 줄지는 모르겠지만 저에게는 효과가 있었습니다 💁‍♀️
내 솔루션과 이를 단순화하는 방법에 대한 피드백을 듣고 싶습니다. 또한 이 모든 http 요청 라이브러리를 살펴봐야 합니다. 권장 사항이 있으면 의견에 알려주십시오.

좋은 웹페이지 즐겨찾기