본문 바로가기
Programming/JavaScript

Javascript - 프로미스(Promise)

by Muko 2020. 6. 23.

Promise

  • 원격에서 스크립트를 불러오는 것과 같이 시간이 걸리는 일을 비동기로 처리할 수 있도록 해주는 자바스크립트 객체.

구성

const promise = new Promise((resolve, reject) => {
  // executor
});
  • new Promise 에 전달되는 함수는 executor(실행자, 실행 함수). 인자로 resolve와 reject를 받음.
  • resolve(value) - executor가 정상적으로 끝난 경우, 그 결과를 나타내는 value와 함께 호출
  • reject(error) - 에러 발생 시 에러 객체를 나타내는 error와 함께 호출

new Promise 생성자가 반환하는 promise 객체는 다음과 같은 내부 프로퍼티를 갖는다.

  • state - pending(보류) 로 시작해서 resolve 가 호출되면 fulfilled, reject 가 호출되면 rejected 로 변함.
  • result - undefined로 시작해서 resolve 가 호출되면 value로, reject(error) 가 호출되면 error로 변함.

특징

  • Promise는 반드시 resolve나 reject 중 하나를 호출해야한다. 만약 둘 중 하나가 호출된 상황이라면, 그 뒤에 코드는 무시된다.
  • resolve나 reject는 인수를 최대 하나만 받고, 그 외의 인수는 무시한다.

then, catch, finally

1. then

const promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("done!"), 1000);
});

// resolve 함수는 .then의 첫 번째 함수(인수)를 실행합니다.
promise.then(
  result => alert(result), // 1초 후 "done!"을 출력
  error => alert(error) // 실행되지 않음
);

.then의 첫 번째 인수는 resolve로 Promise가 정상적으로 수행되었을 때 실행되는 함수이고, 두 번째 인수는 reject의 역할을 한다.

작업이 성공적으로 처리된 경우만 다루고 싶다면 .then에 인수를 하나만 전달하면 된다.

2. catch

에러가 발생한 경우만 다루고 싶다면 .then(null, errorHandlingFunction) 과 같이 null 을 첫 번째 인수로 전달하면 된다. .catch(errorHandlingFunction)은 위의 방법과 동일하게 에러가 발생한 경우만 다룰 수 있게 해주는 내부 메서드이다.

let promise = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error("에러 발생!")), 1000);
});

// .catch(f)는 promise.then(null, f)과 동일하게 작동합니다
promise.catch(alert); // 1초 뒤 "Error: 에러 발생!" 출력

3. finally

try {...} catch {...} 에 finally 절이 있는 것처럼, Promise에도 finally 가 있다. Promise는 처리 후에 반드시 resolve 혹은 reject가 실행된다는 점에서 .finally(f)의 호출은 .then(f, f)와 유사하지만, 완전히 같지는 않다.

  • finally 핸들러에는 인수가 없다. finally에서는 Promise가 이행되었는지 거부되었는지 알 수 없다. 그래서 보통 절차를 마무리하는 '보편적' 동작을 수행한다.
  • finally 핸들러는 자동으로 다음 핸들러에 결과와 에러를 전달한다.
new Promise((resolve, reject) => {
  setTimeout(() => resolve("결과"), 2000)
})
  .finally(() => alert("프라미스가 준비되었습니다."))
  .then(result => alert(result)); // <-- .then에서 result를 다룰 수 있음
new Promise((resolve, reject) => {
  throw new Error("에러 발생!");
})
  .finally(() => alert("프라미스가 준비되었습니다."))
  .catch(err => alert(err)); // <-- .catch에서 에러 객체를 다룰 수 있음

콜백과의 차이점

  1. 프라미스
    • 코드의 흐름이 자연스럽다.
    • 원하는 만큼 .then을 호출할 수 있다.
  2. 콜백
    • 콜백을 사용하는 함수가 있을 경우, 콜백이 먼저 준비되어 있어야 한다. 따라서 해당 함수가 호출하기 이전에 호출 결과로 무엇을 할지, 그리고 콜백이 어떻게 동작하는지 미리 알고 있어야 한다.
    • 콜백은 하나만 호출이 가능하다.

댓글0