Promise를 이해해보자! (2탄)

Let's TECH🧐·2022년 5월 23일
0

Today I Learned

목록 보기
5/6
post-thumbnail

resolve와 reject

지난 블로깅에서 배웠다시피 promise 객체는 아래와 같은 문법으로 만들어질 수 있다.

예제 1)

let promise = new Promise(function(resolve, reject) {
  // executor
});

설명

여기서 new Promise에 전달되는 함수는 executor(실행자, 실행 함수)라고 부른다.
executor는 new Promise가 만들어질 때 자동으로 실행된다. executor의 인수 resolvereject는 자바스크립트에서 자체적으로 제공하는 콜백이기 때문에 개발자는 해당 부분을 신경쓰지 않고 executor 안의 코드만 작성하면 된다.

대신 executor에서는 상황에 맞게 인수로 넘겨준 콜백 중 하나를 반드시 호출해야 한다.

  • resolve(value): 일이 성공적으로 끝난 경우 그 결과를 나타내는 value와 함께 호출
  • reject(error): 에러 발생 시 에러 객체를 나타내는 error와 함께 호출

위 내용을 요약하자면,
executor는 new Promise가 만들어질 때 자동으로 실행된다. executor에 해당하는 부분이 처리되고 나면 executor는 처리 성공 여부에 따라 resolvereject를 호출한다.

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

  • state: 처음에는 "pending" 상태였다가 resolve가 호출되면 "fullfilled", reject가 호출되면 "rejected"로 변경된다.
  • result: 처음에는 "undefined"이었다가 resolve(value)가 호출되면 value로, reject(error)가 호출되면 error로 변경된다.

다음 예제는, 지난 블로깅에서 비슷한 예제로 promise 생성자와 간단한 executor 함수로 만든 예시이다.

예제 2)

(1) 성공적으로 이행된 프로미스

let promise = new Promise(function(resolve, reject) {
	// 프로미스가 만들어지면 executor 함수는 자동으로 실행된다.
  
	// 1초 뒤에 일이 성공적으로 끝났다는 신호가 전달되면서 result는 '완료'가 된다.
	setTimeout(() => resolve("완료"), 1000);
})

executor 처리가 시작된 지 1초 후, resolve("완료")가 호출되고, 결과가 만들어진다.
이 때, promise 객체의 상태는 다음과 같이 변한다.

				    resolve("완료")
state: "pending"         ->        state: "fulfilled" 
result: "undefined"      ->        result: "완료"

위와 같이 일이 성공적으로 처리되었을 때의 프로미스를 fulfilled promise(약속이 이행된 프로미스) 라고 부른다.

(2) 거부된 프로미스

이번에는 executor가 에러와 함께 약속한 작업을 거부하는 경우에 대해 살펴보자.

let promise = new Promise(function(resolve, reject) {
  // 1초 뒤에 에러와 함께 실행이 종료되었다는 신호를 보낸다.
  setTimeout(() => reject(new Error("에러 발생!")), 1000);
});

1초 후 reject(...)가 호출되면 promise의 상태가 "rejected"로 변한다.

				  reject(Error 객체)
state: "pending"         ->        state: "rejected" 
result: "undefined"      ->        result: Error 객체

위 내용을 요약해보면, executor는 보통 시간이 걸리는 일을 수행하며 해당 일이 끝나면 resolve나 reject 함수를 호출하는데, 이때 프라미스 객체의 상태가 변하게 된다.
이행(resolved) 혹은 거부(rejected) 상태의 프라미스는 처리된(settled) 프라미스라고 부르고, 반대되는 프라미스로는 대기(pending) 상태의 프라미스가 있다.

then, catch

executor가 처리되고 난 후 처리된 결과나 에러를 받을 함수.then, .catch 메서드를 사용해 등록된다.

then

.then은 프로미스에서 가장 중요한 메서드이다.

promise.then(
	function(result) { /* 결과(result)를 다룬다 */ },
	function(error) { /* 에러(error)를 다룬다 */ }
);

.then의 첫번째 인수는 프로미스가 이행되었을 때 실행되며, 여기서 실행 결과를 받는다.
.then의 두번째 인수는 프로미스가 거부되었을 때 실행되며, 에러를 받는다.

(1) 성공적으로 이행된 프로미스

그렇다면, 성공적으로 이행된 프로미스의 예시를 한번 살펴보자.

let promise = new Promise(function(resolve, reject) {
	setTimeout(() => resolve("완료!"), 1000);
});

// executor가 처리되고 난 후 then을 통해 처리된 결과나 에러를 받음
// resolve 함수는 .then의 첫번째 함수를 실행
promise.then(
	result => alert(result), // 1초 후 "완료!" 출력
	error => alert(error) // 실행되지 않음
);

(2) 거부된 프로미스

반면, 프로미스가 거부된 경우에는 아래와 같이 두번째 함수가 실행된다.

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

// resolve 함수는 .then의 두번째 함수를 실행
promise.then(
	result => alert(result), // 실행되지 않음
	error => alert(error) // 1초 후 "Error: 에러 발생!"을 출력
);

catch

프로미스가 이행되거나 거부된 경우 둘 중 프로미스가 거부되어 에러가 발생한 경우만 다루고 싶다면 .then(null, errorHandlingFunction) 과 같이 null을 첫번째 인수로 전달하면 된다. 또한, .catch(errorHandlingFunction)를 사용하는 것도 가능하며 .catch.thennull을 전달하는 것과 동일하게 작동한다.

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

// executor가 처리되고 난 후 catch를 통해 에러를 받음
// .catch(f)는 promise.then(null, f)과 동일하게 작동
promise.catch(alert); // 1초 뒤 "Error: 에러 발생!" 출력

참고 사이트

모던 자바스크립트 튜토리얼 - 프라미스

profile
Minju's Tech Blog

0개의 댓글