개발에 AtoZ까지

[ES6][JS] Javascript 비동기 처리(Promise) 2탄 본문

카테고리 없음

[ES6][JS] Javascript 비동기 처리(Promise) 2탄

AtoZ 개발자 2021. 1. 31. 13:58
반응형

◆목표

Promise 등장 배경 및 정의
Promise 사용법
콜백 지옥에 대한 Promise 해결법
Promise의 기타 문법

1. Promise 등장 배경 및 정의

- 콜백함수의 단점인 콜백 지옥을 해결하기 위해 등장

- 비동기적 처리의 근본적인 문제점이였던 서버에서 데이터를 받아오기 전에 화면에 데이터를 표시하려고 할 때 발생하는 오류를 해결하기 위해 등장

- ES6에서 부터 추가된 문법으로 비동기 처리를 위해 기존에 있던 단점들을 보완하기 위해 사용됨

 

2. Promise 사용법

  1. promise 객체를 생성
  2. promise 객체는 executor라는 함수가 내부적으로 자동적으로 실행되는데 executor 함수에서는 resolve와 reject라는 두개의 함수를 인자로 받아서 비동기 처리 함수를 실행함  
  3. executor를 통해 비동기 처리 함수를 실행 완료 후에 해당 작업이 성공하면 resolve 함수를 실패하면 reject 함수를 호출한다.
  4. resolve, reject 함수 정의는 then() 메소드를 사용해서 정의해주면 된다.
//Promise 객체 생성
const promise_test = new Promise((resolve, reject) => {
  //비동기 작업 수행
  setTimeout(() => {
    let num = 10;
    if (num >= 9) {
      resolve("성공: " + num);
    } else {
      reject("실패: " + num);
    }
  }, 1000);
});

//promise 객체를 실행시켜줄 then 메소드 사용
promise_test.then((str)=>{
  //성공했을때 실행, str 매개변수는 promise 실행시 넘오는 값이라고 생각하면됨
  console.log(str);
},(str)=>{
  //실패했을때 실행
  console.log(str);
}
);

3. 콜백지옥에 대한 Promise 해결법

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    let num = 1;
    if (num == 1) {
      resolve(num);
    } else {
      reject("error");
    }
  }, 500);
});

//실행 순서에 맞출 필요가 있을 경우,  then을 이어서 작성해줌(콜백지옥에서 해방됨)
promise
  .then(
    (num) => {
      console.log(num);
    },
    (err) => {
      console.log(err);
    }
  )
  .then(() => {
    console.log("close");
  });

4. Promise의 기타 문법

1) catch 메서드

- 실행 중, 예외 상황(오류)을 처리함

- then 메서드에 failureCallback 함수를 정의하지 않은 상황에서 실패한 경우에도  catch 메서드가 호출됨

- 보통 catch문을 chaining(아래 참고)의 맨 마지막에 추가해서, 전체 코드의 에러 케이스를 핸들링함

const asyn = new Promise((resolve, reject) => {
  setTimeout(() => {
    let num = 2;
    if (num == 1) {
      resolve(num);
    }
    //실패했을경우 에러를 발생시킴
    reject(new Error("에러가 발생함"));
  }, 500);
});

asyn
  .then((num) => {
    console.log(num);
  })
  //에러가 발생해서 catch 메소드로 들어옴
  .catch((error) => {
    console.log(error);
  });

Tip) throw 메서드

- 사용자 정의 예외를 던질 때 사용

- catch 블록이 있으면 catch 블록으로 전달되고, 그렇지 않으면 프로그램을 종료함

- 보통 다음과 같은 구문으로 사용됨(Error 클래스의 객체를 만들어서, 전달함)

const asyn = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve();
  }, 500);
});

asyn
  .then(() => {
    console.log("성공");
    //강제적으로 에러를 호출함
    throw new Error("에러가 발생함");
  })
  //에러가 발생해서 catch 메소드로 들어옴
  .catch((error) => {
    console.log(error);
  });

2) chaining

- then 메서드를 연결해서, 순차적으로 실행되야할 코드를 연결할 수 있음

- then과 catch 메서드로 함께 연결해서 실행 가능함

const asyn = new Promise((resolve, reject) => {
  console.log("start");
  resolve();
});

asyn
  .then(() => {
    console.log("1");
  })
  .then(() => {
    console.log("2");
    throw new Error("error");
  })
  .catch((err) => {
    console.log(err);
  });

예제 1번(catch 위치랑 상관없이 그 뒤 then이 실행됨)

const asyn = new Promise((resolve, reject) => {
  console.log("start");
  resolve();
});

asyn
  .then(() => {
    console.log("1");
    throw new Error("error");
  })
  .catch((err) => {
    console.log(err);
  })
  .then(() => {
    console.log("2");
  });

예제 2번

3) chaining과 return 

-상위 chaining에서 return을 하면 다음 chaining에서 매개변수로 받아서 재사용이 가능함

const asyn = new Promise((resolve, reject) => {
  console.log("start");
  resolve(1);
});

asyn
  .then((num) => {
    console.log(num);
    return num;
  })
  .then((num) => {
    console.log(num + 1);
    throw new Error("error");
  })
  .catch((err) => {
    console.log(err);
  })

4) finally 메서드

- promise의 결과값이 resolve(성공)든 reject(실패)든 무조건 실행하게 하는 메서드

const asyn = new Promise((resolve, reject) => {
  console.log("start");
  let flag = true;
  if (flag) {
    resolve(flag);
  }
});

asyn
  .then(
    (flag) => {
      console.log("성공: " + flag);
    },
    () => {
      console.log("실패");
    }
  )
  .finally(() => {
    console.log("finally 호출");
  });
const asyn = new Promise((resolve, reject) => {
  console.log("start");
  let flag = true;
  if (flag) {
    resolve(flag);
  }
});

asyn
  .then(
    (flag) => {
      console.log("성공: " + flag);
      throw new Error("에러발생");
    },
    () => {
      console.log("실패");
    }
  )
  //finally은 finally 메소드 나오기 전까지의 then만 신경씀,

  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("finally 호출");
  })
  .then(() => {
    console.log("catch문 다음 then");
  });

5) Promise.all 메서드

- 동기화 처리할 Promise를 묶어서 한 번에 실행

- 묶은 Promise가 모두 실행된 후에, then 구문을 실행함

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("p1");
  }, 500);
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("p2");
  }, 100);
});

Promise.all([p1, p2]).then((data) => {
  console.log(data);
});

6) Promise.race 메서드

- 동기화  처리할 Promise를 묶어 놓은 것 중 1개라도 먼저 끝났을 때 then 구문을 실행함

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("p1");
  }, 500);
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("p2");
  }, 100);
});

Promise.race([p1, p2]).then((data) => {
  console.log(data);
});
반응형
Comments