Promise
then 과 catch 로 결과를 받습니다. 대기·이행·거부 상태를 봅니다.
나중에 올 값을 지금 손에 쥡니다
앞 단원에서는 결과를 콜백 안에서만 쓸 수 있었습니다. Promise 는 다릅니다 — 오래 걸리는 일을 시작하면 그 자리에서 무언가를 돌려줍니다. 아직 값은 없지만, 나중에 값이 올 자리입니다.
그것을 손에 쥐고 있으므로 변수에 담고, 넘기고, 이어 붙일 수 있습니다. 콜백으로는 할 수 없던 일입니다.
Promise 는 세 상태 가운데 하나입니다.
- 대기(pending) — 아직 끝나지 않았습니다.
- 이행(fulfilled) — 끝났고 값이 있습니다.
- 거부(rejected) — 실패했고 이유가 있습니다.
만들고 받기
const promise = new Promise(resolve => { setTimeout(() => resolve("완료"), 100); }); console.log(promise); promise.then(value => console.log(value)); console.log("먼저 실행됩니다");
첫 줄에서 이미 무언가가 손에 있습니다. 아직 값은 없지만 변수에 담았습니다.
then 에 넘긴 함수는 값이 왔을 때 불립니다.
resolve 를 부르는 순간 대기에서 이행으로 바뀝니다.
Promise 를 직접 만드는 일은 많지 않습니다 — 대개는 이미 Promise 를 돌려주는
함수를 사용합니다(5.5 의 fetch).
성공과 실패
const ok = Promise.resolve("성공"); const fail = Promise.reject(new Error("실패")); ok.then(value => console.log("then:", value)); fail.catch(error => console.log("catch:", error.message));
Promise.resolve 와
Promise.reject 는 이미 끝난 Promise 를 바로
만듭니다. 시험할 때 편합니다.
오류 처리가 한 자리로 모입니다. 콜백처럼 단계마다 첫 인자를 검사하지 않습니다.
이어 붙이기
then 은 또 Promise 를 돌려줍니다. 그래서 계속
이을 수 있습니다. 앞의 then 이 돌려준 값이 다음
then 으로 넘어갑니다.
Promise.resolve(2) .then(n => n * 10) .then(n => { console.log(n); return n + 5; }) .then(n => console.log(n));
5.2 의 콜백 지옥과 견주어 보세요. 단계가 늘어도 오른쪽으로 밀리지 않고 아래로 이어집니다.
중간에 실패하면
Promise.resolve(5) .then(n => { console.log("첫째", n); throw new Error("여기서 실패"); }) .then(n => console.log("둘째", n)) .catch(error => console.log("잡았습니다:", error.message)) .finally(() => console.log("끝났습니다"));
실패하면 중간의 then 들을 건너뛰고 가장 가까운
catch 로 갑니다. "둘째" 가 나오지 않은 까닭입니다.
finally 는 성공이든 실패든 마지막에 한 번
실행됩니다. 로딩 표시를 끄는 자리로 자주 사용합니다(5.6).
여러 개를 한꺼번에
function delay(ms, value) { return new Promise(resolve => setTimeout(() => resolve(value), ms)); } Promise.all([delay(300, "가"), delay(100, "나"), delay(200, "다")]) .then(values => console.log(values));
Promise.all 은 모두 끝나기를 기다렸다가 결과를
배열로 돌려줍니다. 차례는 끝난 순서가 아니라 넣은 순서입니다.
셋을 차례로 기다리면 600밀리초가 걸리지만, 이렇게 하면 가장 오래 걸리는 것 하나인 300밀리초에 끝납니다.
처음에 자주 걸리는 것
돌려준 값이 다음 then 으로 넘어갑니다. 빠뜨리면
다음 단계가 undefined 를 받습니다.
.then(n => { n * 10; }) // 다음이 undefined 를 받습니다
.then(n => n * 10) // 이렇게 적습니다
실패했는데 받는 곳이 없으면 조용히 지나가거나 콘솔에만 남습니다. 사용자는 아무것도 모른 채 빈 화면을 봅니다.
const value = promise; 는 값이 아니라 Promise
입니다. 값은 then 안에서, 또는 다음 단원의
await 로 꺼냅니다.
직접 해보기
밀리초를 받아 그만큼 뒤에 이행되는
delay 함수를 만들고, 0.1초 뒤
"끝" 을 출력하세요.
숫자를 받아 0.1초 뒤 그 제곱을 돌려주되, 음수면 거부하는 함수를 만드세요. 성공과 실패를 각각 한 번씩 불러 결과를 출력합니다.
new Promise((resolve, reject) => ...) 로 둘 다 받습니다.이 단원의 정리
- Promise 는 나중에 올 값이 놓일 자리입니다. 그 자리에서 바로 돌려받습니다.
- 상태는 대기 · 이행 · 거부 셋입니다.
then으로 값을,catch로 실패를 받습니다.then이 또 Promise 를 돌려주므로 아래로 이어집니다.Promise.all은 모두 끝나기를 기다립니다. 차례는 넣은 순서입니다.