자바스크립트 Promise 정리

vhv3y8·2023년 3월 11일
0

자바스크립트

목록 보기
1/16

동기와 비동기 synchronous and asynchronous

코드가 동기적으로 실행된다는 건 한 줄의 실행이 끝난 뒤에 다음 줄이 실행되기 시작하는거다.

비동기적으로 실행된다는 건 한 줄의 실행이 끝날 때까지 기다리지 않고 다음 줄을 실행하는거다.

console.log(1);
setTimeout(() => {
  console.log(2);
}, 1000);
console.log(3);
1
3
2

한 번쯤 봤을 법한 이 예시를 보자.

setTimeout()은 비동기 함수다.

1초 뒤에 console.log(2)가 포함된 함수를 실행하기로 하지만, 끝까지 기다리지 않고 다음 줄을 실행하게 된다.

콜백 callback

콜백은 정의상 함수에 파라미터로 함수를 넘겨줘서 원할 때 실행할 수 있게 해주는거다.

setTimeout()의 첫 번째 파라미터에 받는 함수도 원하는 시간(입력받은 시간) 뒤에 실행되도록 하는거니까 콜백이라고 볼 수 있다.

비동기 함수와 콜백

콜백은 이런 식의 비동기 함수들의 실행이 끝난 뒤에나 그 결과값으로 무언가를 하는 데에 사용되곤 한다.

만약에 비동기 함수를 실행하고 바로 다음 줄에 그 결과값을 갖고 무언가를 하는 코드를 적는다면, 결과값이 나오기 전에 실행되버릴 수 있다.

그래서 그 비동기 함수에다가 그 결과값을 갖고 실행할 함수 자체를 파라미터로 넘겨줘버리고, 다 끝난 뒤에 그 함수를 실행하도록 함수 내부에다가 적어주는 느낌인거다.

따라서 비동기 함수와 콜백은 연관성이 깊다.

결과값이 나온 뒤에 그 결과값으로 무언가를 하고 싶은 경우가 많기 때문이다.

특히 그 결과값을 보고 조건을 체크해서 성공 / 실패 여부에 따라서 다른 함수를 실행하는 등의 목적을 위해 여러 개의 콜백을 받기도 한다.

이런 과정을 조금 더 쉽고 간편하게 해주는 게 Promise라고 할 수 있다.

Promise

Promise는 결과값이 나오면 콜백을 실행해주겠다는 약속이라고 볼 수 있다.

Promise() constructor

new Promise(executor);

프로미스는 파라미터에 함수를 하나 건네주는 식으로 만들어진다.

이 함수(executor)는 두 개의 함수를 파라미터로 받는데, 간단히 말해 상태가 성공인지 실패인지 결정할 때 불러줄 목적으로 존재한다.

함수 내부에서는 비동기적인 걸 쭉 하다가, 성공일 땐 첫 번째 함수를 결과값과 함께 실행해주면 되고, 실패일 땐 두 번째 함수를 결과값과 함께 실행해주면 된다.

그러니까 실패인 경우가 없고 그냥 결과값으로 뭔가를 할려고 하는 경우면, 다 끝난 뒤에 첫 번째 함수를 부르면서 결과값을 넘겨주면 되는거다.

new Promise((res, rej) => {
	res(1);
});

간단한 예시는 이렇게 쓸 수 있다.

함수 이름은 보통 (resolve, reject) 혹은 약자로 (res, rej)라고 쓰곤 한다.

이 함수들은 그냥 Promise의 상태를 결정하면서, 콜백들을 시작하라는 의미로 불러주는거 정도라고 생각하면 되는 느낌이다.

프로미스의 상태 States

Promise에는 3가지 상태가 있다.

  • fulfilled - 성공적이라는 상태
  • rejected - 실패했다는 상태
  • pending - fulfilled도 아니고 rejected도 아닌 상태.

상태는 아니지만, fulfilled이거나 rejected인 걸 settled라고 표현하기도 한다.

let a = new Promise((res, rej) => { });
console.log(a);
Promise { <pending> }

프로미스를 resolve 하지도 않고 reject하지도 않으면 영원히 pending 상태로 남게 된다.

또는 프로미스 안의 내용이 실행 중일 때(resolve나 reject가 불러지지 않았을 때) 프로미스를 부르면, pending 상태라고 나온다.

그렇다면 성공했을 때와 실패했을 때의 콜백은 어디에 적어줘야 하는걸까?

Promise.prototype.then(), Promise.prototype.catch()

둘 다 프로미스에 해당하는 콜백을 적어주는 함수이다.

then()성공했을 시 실행할 함수를 필수로 받고, 실패했을 시 실행할 함수를 선택적으로 두 번째에 받을 수 있다.

catch()실패했을 시 실행할 함수 하나를 받는다.

앞서 적었듯, 성공했을 시 실행할 함수new Promise() 할 때의 첫 번째 파라미터에 해당하는 함수를 부르면 실행되는거고, 실패했을 시 실행할 함수는 두 번째 파라미터에 해당하는 함수를 부를 때 실행된다.

따라서 당연하게도 Promise 내부의 내용이 끝나서 본인이 적은대로 두 파라미터 중 하나를 부르거나 할 때까지 이 콜백들은 실행되지 않는거고, 다르게 말해 비동기 함수의 결과값이 나오면 실행될거라는 보장이 있다.

리턴값

참 재밌는(머리 아픈) 점은, 이 두 메소드 또한 Promise를 리턴한다는거다.

이 예시 (콜백 | javascript.info)에서도 나오듯이, 비동기 함수의 결과값을 갖고 또 다른 비동기 함수를 실행하는 경우도 충분히 나올 수 있다.

이럴 때 Promise를 리턴하면서 비동기 함수를 또 내부에 적어주고 resolve하거나 reject하면서 결과값을 넘겨주는 식으로 쭉쭉 이어주는 체이닝(chaining)을 할 수 있는거다.

간단하게 그냥 then() 안에 첫 번째 콜백만 적어주면서 결과값으로 무언가를 하고 있었다고 해보자.

그러면 지금까지는 동기적으로 코드가 실행되서 결과값을 갖게 됐다고 생각해버려도 무방하고, 여기서 비동기적으로 뭔가를 해야하면 Promise를 만들면서 그 안에 비동기적인 걸 실행해주고 그걸 리턴만 해주면 되는거다.

당연히 콜백에서 반드시 Promise를 리턴해야 하는 건 아니고, 그냥 결과값 받아서 할 거 하고 그대로 끝나는 게 일반적이라고 볼 수 있다.

이 링크 (Promise.prototype.then()#반환값 | MDN)를 보면 결과값으로 어떻게 Promise를 만드는지 나온다.

대충 요약하면 어떤 값을 return할 시 그 값으로 fulfilled되고, 아무 값도 리턴하지 않을 시 undefined로 fulfilled되고, Error를 throw 할 시 그 값으로 rejected 된다.

당연하게도, 할 거 하고 끝나는 거면 뭐가 리턴되는지 신경 쓸 필요는 없다.

참고

profile
미래의 나에게 설명하기

0개의 댓글