비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
[출처: MDN web docs]
JavaScript는 싱글스레드 언어지만 시간이 오래 걸릴 수 있는 몇몇 작업들은 비동기적으로 처리된다.
이때 비동기처리방식은 다음문서를 참고.
대표적인 예시로
Promise는 위에서 언급한 비동기 작업들을 효과적으로 하기 위해 도입된 기능이다.
기존 비동기 작업을 순서에 맞게 처리하려 하면 다음과 같이 코드를 작성해야 했다.
다음은 setTimeout이 있는 작업들의 실행순서를 보장하는 예시다.
function task1(callback) {
setTimeout(() => {
console.log("작업 1 완료");
callback();
}, 1000);
}
function task2(callback) {
setTimeout(() => {
console.log("작업 2 완료");
callback();
}, 1000);
}
function task3(callback) {
setTimeout(() => {
console.log("작업 3 완료");
callback();
}, 1000);
}
task1(() => {
task2(() => {
task3(() => {
console.log("모든 작업 완료!");
});
});
});
task1, 2, 3 들여쓰기가 한없이 깊어질 수 있다. 만약 더 복잡한 로직으로 더 많은 작업들을 위와 같이 처리한다면 코드 가독성이 더 떨어지게 된다.
이를 Promise를 활용하면 다음과 같이 처리할 수 있다.
function task1() {
return new Promise(resolve => {
setTimeout(() => {
console.log("작업 1 완료");
resolve();
}, 1000);
});
}
function task2() {
return new Promise(resolve => {
setTimeout(() => {
console.log("작업 2 완료");
resolve();
}, 1000);
});
}
function task3() {
return new Promise(resolve => {
setTimeout(() => {
console.log("작업 3 완료");
resolve();
}, 1000);
});
}
// Promise 체이닝
task1()
.then(task2)
.then(task3)
.then(() => console.log("모든 작업 완료!"));
Promise객체는 함수를 매개변수로 받고, 그 함수의 실행 상태를 반환하는 객체이다.
반환할 수 있는 상태는 다음과 같다.
다음은 Promise 사용 예제다.
let myPromise = new Promise((resolve, reject) => {
let success = true; // 성공 가정
setTimeout(() => {
if (success) {
resolve("작업 성공!");
} else {
reject("작업 실패!");
}
}, 2000);
});
console.log(myPromise); // Promise { <pending> }
2초가 지나지 않았기 때문에 console.log에는 pending이 나온다.
Promise 상태가 완료일 경우 실행한다.
let myPromise = new Promise((resolve, reject) => {
let success = true; // 성공 가정
setTimeout(() => {
if (success) {
resolve("작업 성공!");
} else {
reject("작업 실패!");
}
}, 2000);
});
myPromise.then(result => {
console.log("성공:", result);
});
Promise 상태가 실패일 경우 실행한다.
let myPromise = new Promise((resolve, reject) => {
let success = false; // 실패 가정
setTimeout(() => {
if (success) {
resolve("작업 성공!");
} else {
reject("작업 실패!");
}
}, 2000);
});
myPromise.catch(error => {
console.error("실패:", error);
});
Promise 상태가 성공이든 실패든 관계없이 실행한다.
myPromise.finally(() => {
console.log("작업 완료!");
});
다음과 같이 then과 catch 등으로 체이닝을 하여 실행순서를 보장할 수 있다.
new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000); // 1초 후 1 반환
})
.then(result => {
console.log(result); // 1
return result * 2;
})
.then(result => {
console.log(result); // 2
return result * 3;
})
.then(result => {
console.log(result); // 6
})
.catch(error => {
console.error("에러 발생:", error);
});
여러개의 Promise를 배열로 받아 병렬 실행하고, 모든 Promise가 성공해야만 then()이 실행된다.
이때 하나라도 실패하면 catch()가 실행된다.
let p1 = new Promise(resolve => setTimeout(() => resolve("첫 번째 완료"), 1000));
let p2 = new Promise(resolve => setTimeout(() => resolve("두 번째 완료"), 2000));
let p3 = new Promise(resolve => setTimeout(() => resolve("세 번째 완료"), 3000));
Promise.all([p1, p2, p3])
.then(results => console.log("모든 작업 완료:", results))
.catch(error => console.error("에러 발생:", error));
가장 빨리 실행완료된 Promise의 결과만 반환(성공/실패)
let p1 = new Promise(resolve => setTimeout(() => resolve("첫 번째 완료"), 1000));
let p2 = new Promise(resolve => setTimeout(() => resolve("두 번째 완료"), 2000));
let p3 = new Promise(resolve => setTimeout(() => resolve("세 번째 완료"), 3000));
Promise.race([p1, p2, p3])
.then(result => console.log("가장 먼저 완료된 작업:", result));
모든 Promise의 결과를 배열로 반환
let p1 = new Promise(resolve => setTimeout(() => resolve("첫 번째 완료"), 1000));
let p2 = new Promise(resolve => setTimeout(() => resolve("두 번째 완료"), 2000));
let p3 = new Promise(resolve => setTimeout(() => resolve("세 번째 완료"), 3000));
Promise.allSettled([p1, p2, p3])
.then(results => console.log("모든 작업 결과:", results));
가장 빨리 성공한 Promise의 결과 반환
let p1 = new Promise(resolve => setTimeout(() => resolve("첫 번째 완료"), 1000));
let p2 = new Promise(resolve => setTimeout(() => resolve("두 번째 완료"), 2000));
let p3 = new Promise(resolve => setTimeout(() => resolve("세 번째 완료"), 3000));
let p4 = new Promise((_, reject) => setTimeout(() => reject("에러"), 500));
Promise.any([p4, p1, p2])
.then(result => console.log("가장 먼저 성공한 작업:", result))
.catch(error => console.error("모든 작업 실패:", error)); // p1성공시 반환