프로미스 (Javascript)

Cramming An·2022년 7월 29일
0

JS Interview

목록 보기
7/7
post-thumbnail

배경

  • Callback 패턴의 단점 보완

Callback

  • 하나의 함수가 가지는 공통적인 로직을 여러번 활용하기 위해, 공통 로직은 정의해 두고, 변경되는 로직은 추상화하여 함수 외부에서 내부로 로직을 전달할 필요성 생김
  • 함수의 매개변수로써 함수 (변경되는 로직)를 이용
  • 이 때, 함수의 매개변수를 통해 내부로 전달되는 함수를 callback 함수 라고 한다.
  • 그리고 함수를 매개변수로써 전달 받은 함수를 고차 함수라고 한다.

📌 Hook 이전, Class 기반의 React에서 고차함수를 통해 state 가 있는 컴포넌트를 재사용 하곤 했다.

Callback과 비동기

비동기 함수의 문제점

  • 콜백함수를 인자로 하는 비동기 함수 실행 이후, 물리적으로 다음 코드에는 콜백함수의 실행 결과가 전혀 반영되지 않는다. (브라우저에 의해 모든 콜 스택이 pop 된 이 후에 콜 스택에 push 되므로)
  • 다시 말해, 비동기 함수의 비동기 처리 결과를 외부에 반환할 수 없다.
  • 따라서, 비동기 함수 내부에서, 비동기 처리 결과에 대한 후속 처리를 수행해야 한다.
  • 후속 처리도 하나의 로직이므로, 외부로 부터 받은 함수, 즉 콜백 함수로 후속 처리를 한다.

예시

  • 예를 들어 HTTP를 이용한 GET 요청을 콜백 패턴을 이용해 해볼 것이다.
  • GET 요청이 성공하면 response를 콘솔에 출력하고, 실패하면 에러메시지를 콘솔에 출력할 것 이다.
  • 다음과 같은 과정을 수행한다.
    1. GET 요청을 할 리소스를 함수의 인자로 전달한다.
    2. XMLHttpRequest 생성자 함수를 이용해, 객체를 생성하고 .open,.send,.onload 메서드를 이용해 비동기 작업을 수행한다. (Web API 호출)
    3. 이때 .onload 메서드는 미리 만들어 놓은 콜백함수를 인자로 갖는다.
    4. 브라우저가 해당 비동기 작업을 끝낸 후, 콜백함수는 태스크 큐를 거쳐 콜 스택으로 올라온다.
    5. 콜백함수는 비동기 작업을 끝낸 XMLHttpRequest 객체를 참조하므로, 객체의 상태에 따라 결과를 콘솔에 출력한다.

Callback을 이용한 비동기 처리의 문제점

콜백 헬

  • 비동기 처리 결과를 콜백 함수를 통해 처리를 했다.
  • 그런데, 비동기 처리 결과를 인자로 받는 또 다른 비동기 함수가 있다면, 콜백함수 안에 또다른 비동기 함수가 들어간다.
  • 이런 일이 반복되면 중첩도가 높아져서 복잡도가 늘어난다.

에러처리의 한계

  • 비동기 함수와 콜백함수의 실행은 독립적이다.
  • 하지만 에러는 호출자의 방향(스택의 아래 방향)으로 전파된다.
  • 따라서 비동기 함수를 통해, 콜백 함수의 에러처리를 할 수 없다.

프로미스

  • 비동기 처리 상태(state)와 결과(result)를 관리하는 객체
  • Promise 생성자 함수로 생성이 되고, 콜백 함수를 인자로 받는다.
  • 이 콜백함수는 resolvereject 라는 함수를 인자로 받는다.
  • 프로미스 객체 생성시 콜백 함수는 자동으로 실행 되는데, 이 콜백 함수 내부에서 필요한 비동기 함수를 작성한다.
const promise = new Promise((resolve, reject) => {
  /*여기서 비동기 함수 실행*/
  if (성공시) resolve(결과)
  else reject(실패 이유)
})
  • 콜백 패턴의 콜백 함수가 하는 역할을 resolvereject 라는 함수가 대신한다.
  • resolvereject 함수는 promise 객체의 프로퍼티를 변경시킨다. (state, result)
  • 이 프로퍼티에 접근하는 방법은 프로미스의 후속 처리 메서드를 이용하는 것 이다.
const promise = new Promise((resolve, reject) => {
  /*여기서 비동기 함수 실행*/
  if (성공시) resolve(결과)
  else reject(실패 이유)
})
promise.then((v) => console.log(v), (e) => console.error(e))
  • 핵심은 promise 객체의 메서드를 통해 promise 객체의 프로퍼티를 변경하고, 전역으로 읽어옴으로 비동기 결과를 콜백함수 바깥으로 가져올 수 있다는 점이다.
  • 프로미스의 후속 처리 메서드의 콜백함수는 마이크로태스크 큐 라는 태스크 큐 보다 우선순위가 높은 큐에 enqueue된다.
profile
La Dolce Vita🥂

0개의 댓글