JavaScript_ES6_Study [ Promise ]

이준석·2023년 5월 5일
0

JavaScript_Study

목록 보기
32/35
post-thumbnail

2022-03-15 노션페이지,
2022-03-30 노션페이지,
2022-04-02 노션페이지,
2022-04-25 노션페이지,
2022-05-16 노션페이지,
2022-05-17 노션페이지
기록된 노션을 다시 정리

어려웠던 부분

  • 서버와의 통신에서의 비동기 개념
  • 비동기 통시 예시를 XMLHttpRequest로 배웠으나 XMLHttpRequest의 메소드들을 제대로 이해하지 못해 전체적으로 제대로 이해하지 못함
  • resolve의 역할

1. 콜백 패턴의 단점

콜백헬이란?

만일 비동기 함수의 처리 결과를 가지고 다른 비동기 함수를 호출해야 하는 경우, 함수의 호출이 중첩(nesting)이 되어 복잡도가 높아지는 현상이 발생하는데 이를 Callback Hell이라 한다.

step1(function(value1) {
  step2(value1, function(value2) {
    step3(value2, function(value3) {
      step4(value3, function(value4) {
        step5(value4, function(value5) {
            // value5를 사용하는 처리
        });
      });
    });
  });
});

Callback Hell은 코드의 가독성을 나쁘게 하고 복잡도를 증가시켜 실수를 유발하는 원인이 되며 에러 처리가 곤란하다.

에러 처리의 한계

콜백 방식의 비동기 처리가 갖는 문제점 중에서 가장 심각한 것은 에러 처리가 곤란하다는 것이다.

try {
  setTimeout(() => { throw new Error('Error!'); }, 1000);
} catch (e) {
  console.log('에러를 캐치하지 못한다..');
  console.log(e);
}
  1. setTimeout실행 => 이벤트루프로 내부 콜백함수 Task queue로 이동
  2. setTimeout종료
  3. 호출 스택이 비어졌을 때, 호출 스택으로 이동되어 실행된다
  4. 이때 호출 스택에 setTimeout 함수가 없으므로 콜백 함수를 호출한 것은 setTimeout 함수가 아니다라는 것을 의미한다.
  5. 그렇기 때문에 setTimeout함수 자체에는 에러가 없다고 판단

    setTime함수 설명
    setTimeout 함수는 콜백 함수를 호출한 것이 아니라, 콜백 함수를 실행하기 위한 타이머를 설정한 것이며, 이후에 타이머가 만료되어 콜백 함수가 호출되면 호출 스택에는 setTimeout 함수가 아닌 타이머 메커니즘이 콜백 함수를 호출하게 됩니다.

2. 프로미스의 생성

프로미스는 Promise 생성자 함수를 통해 인스턴스화한다.

// Promise 객체의 생성
const promise = new Promise((resolve, reject) => {
  // 비동기 작업을 수행한다.

  if (/* 비동기 작업 수행 성공 */) {
    resolve('result');
  }
  else { /* 비동기 작업 수행 실패 */
    reject('failure reason');
  }
});

3. 프로미스의 후속 처리 메소드

Promise 객체의 후속 처리 메소드(then, catch)를 통해 비동기 처리 결과 또는 에러 메시지를 전달받아 처리한다.

  • then
    • then 메소드는 두 개의 콜백 함수를 인자로 전달 받는다.
      ( resolve() 안에 있는 데이터를 인자로 받음 )
  • catch
    - 예외(비동기 처리에서 발생한 에러와 then 메소드에서 발생한 에러)가 발생하면 호출된다.

    then(undefined, onRejected)의 모습으로 에러를 처리할 수 있으나 catch 사용이 가독성이 좋고 명확하다.

4. 프로미스 체이닝

여기서 콜백헬 해결이 나온다.
then 메소드가 Promise 객체를 반환하도록 하면(then 메소드는 기본적으로 Promise를 반환한다.)
비동기의

    promiseAjax('GET', `${url}/`)
      // 포스트 id가 1인 포스트를 작성한 사용자의 아이디로 작성된 모든 포스트를 검색하고 프로미스를 반환한다.
      .then(res => promiseAjax('GET', `${url}?userId=${JSON.parse(res).userId}`))
      .then(JSON.parse)
      .then(render)
      .catch(console.error);

5. 프로미스의 정적 메소드

Promise.all

  • 전달받은 모든 프로미스를 병렬로 처리하고 그 처리 결과를 resolve하는 새로운 프로미스를 반환한다.
  • 모든 프로미스의 처리가 종료될 때까지 기다린 후 아래와 모든 처리 결과를 resolve 또는 reject한다.
    (한개라도 예외 발생 시 catch문 실행)
  • 첫번째 프로미스가 가장 나중에 처리되어도 넣은 순서대로 반환됨
  • 한 번에 여러개의 비동기 통신이 필요할 때 사용
Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(console.log) // [ 1, 2, 3 ]
  .catch(console.log);

Promise.race

  • 모든 프로미스를 병렬 처리하는 것이 아니라 가장 먼저 처리된 프로미스가 resolve한 처리 결과를 resolve하는 새로운 프로미스를 반환한다.
  • 말 그대로 레이스 해서 1등만 취급함
Promise.race([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(console.log) // 3
  .catch(console.log);

참조: poiemaweb.com

0개의 댓글