상점에서 물건을 주문하는데 그 물건이 나올 때까지 시간이 걸린다고 가정해보자. 언제 완료되는지는 알 수 없고 가끔 물건을 만들다가 실패하는 경우도 있다. 이럴 때 소비자는 어떡할까? 10초에 한 번씩 물어보면 될까? 가끔 다 됐는지 물으면 만들다가 실패한 경우도 있을 것이다. 그러면 다시 물건을 주문해야 한다.
이럴 때는 상점에 주문을 하고 상품이 준비됐거나 실패하면 알려달라고 하면서 전화번호를 주고 나오는 게 낫다. 그러면 상품이 준비되는 동안 다른 작업도 할 수 있을 것이다. 상점은 이 번호를 기억했다가 작업이 완료되거나 실패했을 때 소비자에게 알려주면 된다. 이럴 때 사용하는 게 바로 Promise이다.
Promise는 이렇게 사용한다. new Promise로 생성한다. 함수를 전달받는데, 이때 인수는 resolve와 reject이다. resolve는 성공한 경우, reject는 실패했을 때 실행되는 함수이다. 이렇게 어떤 일이 완료된 이후 실행되는 함수를 callback함수라고 한다.
new Promise 생성자가 반환하는 Promise 객체는 state와 result를 프로퍼티로 갖는다. state는 초기에 pending이었다가 resolve로 호출되면, 즉 성공하면 fulfilled가 된다. 이때 result는 resolve 함수로 전달된 값이다. 만약 reject가 호출되면, 즉 실패하면 rejected가 된다. 이때 result는 reject 함수로 전달된 에러이다.
코드로 살펴보자. 3초가 걸리도록 setTimeout()을 이용했다. 이 코드는 pending이었다가 3초 후 fulfilled로 바뀐다. result는 undefined였다가 OK가 되는 것이다.
실패를 가정한 코드도 살펴보자. 이 코드는 pending이었다가 3초 후에 rejected로 바뀐다. result는 undefined였다가 3초 후에 error가 되는 것이다.
지금까지 판매자의 코드를 살펴봤다. 판매자는 주문을 받으면 3초 동안 뭔가를 하고 성공인지 실패인지 알려준다. 이제 소비자의 코드를 살펴보자. then을 이용해서 resolve와 reject를 처리할 수 있다. 첫 번째 인수는 promise가 이행되었을 때 실행하는 함수이다. 저 result에는 OK라는 값이 들어온다. 두 번째 인수는 거부되었을 때 실행되는 함수이다. 저 err에는 에러값이 들어올 것이다.
작성하면 이런 모습이다. resolve로 실행되었기 때문에 이 상황에서 두 번째 코드 function(err)는 실행되지 않는다.
then 이외에 사용할 수 있는 것이 catch와 finally이다. catch는 에러가 발생한 경우, 즉 reject인 경우에만 실행된다. 왼쪽 코드는 오른쪽 코드로 바꿀 수 있다. 두 번째로 전달했던 함수를 catch 안으로 넣어주는 것이다. 동일하게 동작한다. 그런데 이렇게 catch로 명확하게 구분하는 편이 가독성도 좋고, 이런 경우 첫 번째 함수로 실행했다가 나는 에러도 잡아줄 수 있으므로 catch를 사용하는 게 훨씬 낫다.
finally는 이행이든 거부든 처리가 완료되면 항상 실행된다. 그래서 이렇게 사용할 수 있다. 로딩 화면 같은 걸 없앨 때 유용하다.
출처: 자바스크립트 중급 강좌 #16 프로미스(Promise)