[JavaScript] Promise란?

Ko Seoyoung·2021년 5월 25일
1

이 글은 비동기에 대한 이해를 바탕으로 합니다.

Promise 란?

Promise 모듈

  • Promise: 비동기 함수 호출 또는 비동기 연산이 완료되었을 때, 이후에 처리할 함수나 에러를 처리하기 위한 함수를 설정하는 모듈 (ES6)

    (자바스크립트에서 비동기 처리가 가장 많이 일어나는 XMLHTTPRequest 처리에서 유용하게 사용)

  • 비동기 연산의 최종 결과(성공 또는 실패)를 나타내는 객체

// Promise 활용 예

function sendEmail(text, timeout){
	return new Promise((resolve, reject) => {
		setTimeout(()=> {
				resolve(text);
		},timeout)
	})
}

sendEmail("To. 교수님께 \n 안녕하세요.", 1000).then((text) =>
	sendEmail(`${text} oo 올림`, 1000)
).then((text) => {
	console.log(`메일 전송완료! 내용: ${text} `);
});

(비동기처리를 setTimeout함수를 사용하여 나타냈다.)

Promise는 왜 생겼을까?

원래는 비동기 처리를 위해 아래와 같이 콜백함수를 사용했다.

ex) 아래 타이머 함수의 첫번째 인자로 넘겨진 함수가 바로 3초 뒤 타이머 함수가 실행된 후 호출될 콜백함수이다.

setTimeout(function() { // callback
	console.log('Bye');
}, 3000);

하지만 콜백함수를 사용하는 경우, 연속적으로 비동기 로직을 처리할 때 다음 코드와 같은 콜백 지옥(Callback hell)이 발생할 수 있다.

setTimeout(function() { // callback1
	console.log('How are you/');
	setTimeout(function() { // callback2
		console.log('I am fine.');
			setTimeout(function() { // callback3
				console.log('Thank you');
				setTimeout(function() { // callback4
					console.log('And you?');
				}, 3000);
			}, 3000);
	}, 3000);
}, 3000);

콜백 안에 계속해서 콜백이 있으니, 이러한 코드 구조는 가독성도 떨어지고 로직을 변경하기도 어렵다.

이러한 로직의 코드를 Promise나 async를 통해 개선할 수 있다.

Promise 모듈은 반환값 (첫번째 예제처럼) Chaining이 가능하므로 순서대로 처리해야 하는 함수들을 쭉 나열해서 호출 가능하다. (→ 순차 보장을 위한 프로그래밍 최소화)

이러한 맥락에서 promise는 콜백을 함수로 넘겨준 것이 아닌 콜백의 반환 결과라고 볼 수도 있다. (콜백 예)

Promise의 세가지 상태

  • pending(대기): fulfilled(이행)도 rejected(거절)도 안된 초기 상태
  • fulfilled(이행): 비동기 연산이 성공적으로 완료된 상태, 결과값을 반환한다.
  • rejected(실패): 비동기 연산에 실패한 상태, 에러를 반환한다.

(+ pending이 아닌, fulfilled 또는 rejected된 상태를 settled(확정) 되었다고 함)

먼저, javascript 비동기 처리의 원리 이해하기

fulfilled 또는 rejected이 발생하면 바로 핸들러가 호출되는 것이 아니라, promise의 then 메서드에 의해 먼저 관련핸들러(콜백함수)들이 콜백큐로 삽입된다. 그 후 콜스택이 비어었을 때, 콜백함수는 이벤트루프에 의해 콜백큐에서 콜스택으로 push 되고, 콜스택에 올라간 콜백함수는 나중에 pop되어 실행된다.

Chained Promises

then()과 catch() 메소드는 Promise 객체를 반환하므로 chaining 형태로 사용될 수 있다.

promise.then(), promise.catch(), promise.finally() 는 promise가 settled(확정) 되었을 때의 액션들을 서로 연결해줌

  • then(): 두개의 인자를 받을 수 있다.

    • 첫번째인자: resolve시 콜백함수

    • 두번째인자: reject시 콜백함수

    • 반환값: 새로 생성된 promise 객체 (chaining으로 사용될 수 있도록)

      .then()에 Promise 객체를 반환하는 콜백 함수가 없어도 비동기 처리는 다음 체인으로 계속 연결된다. 따라서 마지막 .catch()까지 모든 reject 콜백 함수를 안전하게 생략 할 수 있다.


Static methods

  • Promise.all(iterable): 모든 promise가 resolve될 때까지, 또는 한가지라도 reject될 때까지 기다림.
  • Promise.allSettled(iterable): 모든 promise가 settle될 때까지 기다림
  • Promise.any(iterable): promise 중 하나라도 fulfilled되는 즉시 해당 promise의 값으로 resolve
  • Promise.race(iterable) :promise중 하나라도 resolve되거나 reject될 때까지 기다림
  • Promise.reject(reason): 실패 원인과 함께 reject된 Promise 반환
  • Promise.resolve(value): 결과값과함께 resolve된 Promise반환

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise


참고자료

https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

profile
Web Frontend Developer 👩🏻‍💻 #React #Nextjs #ApolloClient

0개의 댓글