π μλ°μ€ν¬λ¦½νΈ Promise κ°λ & λ¬Έλ² μ 볡νκΈ°
μ½λ°± μ§μ₯μ νμΆνλ μλ‘μ΄ λ¬Έλ²
μλ°μ€ν¬λ¦½νΈμμ 'λΉλκΈ° μ²λ¦¬' λ νμ¬ μ€νμ€μΈ μμ κ³Όλ λ³λλ‘ λ€λ₯Έ μμ μ μννλ κ²μ λ§νλ€. μλ₯Ό λ€μ΄ μλ²μμ λ°μ΄ν°λ₯Ό λ°μμ€λ μμ μ μκ°μ΄ 걸리기 λλ¬Έμ μλ°μ€ν¬λ¦½νΈμ μλ² νΈμΆ ν¨μλ λΉλκΈ° ν¨μ(--λ§ν¬--)λ‘ μ΄λ£¨μ΄μ Έ μλ€.
λΉλκΈ°λ νΉμ μ½λμ μ€νμ΄ μλ£λ λκΉμ§ κΈ°λ€λ¦¬μ§ μκ³ λ€μ μ½λλ₯Ό λ¨Όμ μννλ λ°©μμ΄κΈ° λλ¬Έμ, λ§μΌ λΉλκΈ° μμ μ κ²°κ³Όμ λ°λΌ λ€λ₯Έ μμ μ μνν΄μΌ ν λλ μ ν΅μ μΌλ‘ μ½λ°± ν¨μλ₯Ό μ¬μ©νλ€. μ½λ°± ν¨μλ λΉλκΈ° μμ μ΄ μλ£λλ©΄ νΈμΆλλ ν¨μμ μλ―Έλ‘μ, λΉλκΈ° ν¨μμ 맀κ°λ³μλ‘ ν¨μ κ°μ²΄λ₯Ό λκΈ°λ κΈ°λ²μ λ§νλ€. κ·Έλμ ν¨μ λ΄λΆμμ ν¨μ νΈμΆμ ν΅ν΄ λΉλκΈ° μμ μ κ²°κ³Όλ₯Ό λ°μμ μΈμλ‘ μ£Όλ©΄ μ΄λ₯Ό ν΅ν΄ νμ μ²λ¦¬ μμ μ μνν μ μλ€. νμ§λ§ μ½λ°± ν¨μλ₯Ό μ¬μ©νλ©΄ μ½λκ° λ³΅μ‘νκ³ κ°λ μ±μ΄ λ¨μ΄μ§λ λ¬Έμ κ° μλ€. νΉν, μ¬λ¬ κ°μ λΉλκΈ° μμ μ μμ°¨μ μΌλ‘ μνν΄μΌ ν λλ μ½λ°± ν¨μκ° μ€μ²©λμ΄ μ½λμ κΉμ΄κ° κΉμ΄μ§λ νμμ΄ λ°μνλ€. μ΄λ¬ν νμμ μ½λ°± μ§μ₯(callback hell) μ΄λΌκ³ λΆλ₯Έλ€.
μ½λ°± ν¨μμ λΉλκΈ° μ²λ¦¬ λ¬Έλ²
μ«μ n μ νλΌλ―Έν°λ‘ λ°μμμ λ€μ―λ²μ κ±Έμ³ 1μ΄λ§λ€ 1μ© λν΄μ μΆλ ₯νλ μμ
μ setTimeout λΉλκΈ° ν¨μλ‘ κ΅¬νν μ½λμ΄λ€. νλμ λ΄λ μ½λ°±ν¨μλ₯Ό μ°λ¬μ μ¨μ μ½λμ κΉμ΄κ° κΉμ΄μ‘λ€. 보기μ λ§€μ° μμ’μ κ±Έ λ³Ό μ μλ€.
function increaseAndPrint(n, callback) {
setTimeout(() => {
const increased = n + 1;
console.log(increased);
if (callback) {
callback(increased); // μ½λ°±ν¨μ νΈμΆ
}
}, 1000);
}
increaseAndPrint(0, n => {
increaseAndPrint(n, n => {
increaseAndPrint(n, n => {
increaseAndPrint(n, n => {
increaseAndPrint(n, n => {
console.log('λ!');
});
});
});
});
});
μ½λκ° λ§μΉ 'μλ΄κ²'β μ λ§μ κ²μ²λΌ λ€μ¬μ°κΈ° μ½λμ κΉμ΄κ° ν μ²λΌ νμ΄μ Έ μλ μκΈ°λ λͺ¨μ΅μ΄λ€.
μ΄λ¬ν μ½λ°± ν¨μμ μ½λ ννλ μ½λ°± ν¨μκ° μ€μ²©λλ©΄μ λ€μ¬μ°κΈ° μμ€μ΄ κΉμ΄μ Έ μ½λμ κ°λ μ±μ λ¨μ΄λ¨λ¦¬λ©° μ½λμ νλ¦μ νμ νκΈ° μ΄λ €μμ§λ€. λν μ½λ°± ν¨μλ§λ€ μλ¬ μ²λ¦¬λ₯Ό λ°λ‘ ν΄μ€μΌ νκ³ , μλ¬κ° λ°μν μμΉλ₯Ό μΆμ νκΈ° νλ€κ² λλ€.
νλ‘λ―Έμ€λ‘ κ°μ λ λΉλκΈ° μ²λ¦¬ λ¬Έλ²
μ΄λ₯Ό μλ°μ€ν¬λ¦½νΈμ Promise κ°μ²΄λ₯Ό μ΄μ©ν΄ 리ν©ν λ§νλ©΄, λΉλκΈ° μμ
μ κ°μκ° λ§μμ Έλ λ€μ¬μ°κΈ° μ½λμ κΉμ΄κ° κΉμ΄μ§μ§ μκ² λλ€. μμ§ νλ‘λ―Έμ€ λ¬Έλ²μ λν΄ μ λͺ¨λ₯΄μ§λ§ .then() μ ν΅ν΄ μ΄λ€μ μ΄κ±°νμ¬ λΉλκΈ° μ²λ¦¬ κ²°κ³Όλ₯Ό κΉλνκ² νννμμ λ³Ό μ μλ€.
function increaseAndPrint(n) {
return new Promise((resolve, reject)=>{
setTimeout(() => {
const increased = n + 1;
console.log(increased);
resolve(increased);
}, 1000)
})
}
increaseAndPrint(0)
.then((n) => increaseAndPrint(n))
.then((n) => increaseAndPrint(n))
.then((n) => increaseAndPrint(n))
.then((n) => increaseAndPrint(n)); // 체μ΄λ κΈ°λ²
μ΄μ²λΌ μλ°μ€ν¬λ¦½νΈ νλ‘λ―Έμ€λ λΉλκΈ° νλ‘κ·Έλλ°μ κ·Όκ°μ΄ λλ κΈ°λ² μ€ νλμ΄λ€. νλ‘λ―Έμ€λ₯Ό μ¬μ©νλ©΄ μ½λ°± ν¨μλ₯Ό λ체νκ³ , λΉλκΈ° μμ μ νλ¦μ μ½κ² μ μ΄ν μ μλ€. μ§κΈλΆν° μ΄ μλ°μ€ν¬λ¦½νΈμ Promise μ¬μ©λ²μ λν΄ μμ보λλ‘ νμ.
μλ°μ€ν¬λ¦½νΈ νλ‘λ―Έμ€ κ°μ²΄
μλ°μ€ν¬λ¦½νΈ Promise κ°μ²΄λ λΉλκΈ° μμ μ μ΅μ’ μλ£ λλ μ€ν¨λ₯Ό λνλ΄λ Arrayλ Object μ²λΌ λ μμ μΈ κ°μ²΄λΌκ³ 보면 λλ€. λΉλκΈ° μμ μ΄ λλ λκΉμ§ κ²°κ³Όλ₯Ό κΈ°λ€λ¦¬λ κ²μ΄ μλλΌ, κ²°κ³Όλ₯Ό μ 곡νκ² λ€λ 'μ½μ'μ λ°ννλ€λ μλ―Έμμ PromiseλΌ λͺ λͺ μ§μ΄μ‘λ€κ³ νλ€.
νλ‘λ―Έμ€ κ°μ²΄ κΈ°λ³Έ μ¬μ©λ²
νλ‘λ―Έμ€ κ°μ²΄ μμ±
Promise κ°μ²΄λ₯Ό μμ±νλ €λ©΄ new ν€μλμ Promise μμ±μ ν¨μλ₯Ό μ¬μ©νλ©΄ λλ€. μ΄λ Promise μμ±μ μμ λκ°μ 맀κ°λ³μλ₯Ό κ°μ§ μ½λ°± ν¨μλ₯Ό λ£κ² λλλ°, 첫 λ²μ§Έ μΈμλ μμ
μ΄ μ±κ³΅νμ λ μ±κ³΅(resolve)μμ μλ €μ£Όλ κ°μ²΄μ΄λ©°, λ λ²μ§Έ μΈμλ μμ
μ΄ μ€ν¨νμ λ μ€ν¨(reject)μμ μλ €μ£Όλ μ€λ₯ κ°μ²΄μ΄λ€.
Promise μμ±μμμ λ€μ΄κ°λ μ½λ°± ν¨μλ₯Ό executor λΌκ³ λΆλ₯Έλ€.
const myPromise = new Promise((resolve, reject) => {
// λΉλκΈ° μμ
μν
const data = fetch('μλ²λ‘λΆν° μμ²ν URL');
if(data)
resolve(data); // λ§μΌ μμ²μ΄ μ±κ³΅νμ¬ λ°μ΄ν°κ° μλ€λ©΄
else
reject("Error"); // λ§μΌ μμ²μ΄ μ€ν¨νμ¬ λ°μ΄ν°κ° μλ€λ©΄
})
μ μ½λμμ μλ²λ‘λΆν° μμ²νλ λΉλκΈ° μμ
μ΄ μ±κ³΅νλλ μ€ν¨νλλμ λ°λΌ 맀κ°λ³μλ₯Ό νΈμΆνλ κ²μ΄ λλ¨μ λ³Ό μ μλ€. λ§μΌ μμ
μ΄ μ±κ³΅νλ€λ©΄ λΉλκΈ° λ‘μ§ μ€νμ΄ μ°Έμ΄λΌλ κ±Έ μλ €μ£ΌκΈ° μν΄ λ§ κ·Έλλ‘ resolve() μ±κ³΅ λ©μλλ₯Ό νΈμΆνλ€. μ€ν¨νλ©΄ reject() λ©μλλ₯Ό νΈμΆνλ€. λ§μΉ μ€μμΉλ₯Ό λ΄λ € μ κΈ°λ₯Ό νλ₯΄κ² νκ±°λ μ¬λ €μ μνλ₯΄κ² νκ±°λ κ°μ μ리μ΄λ€.
νλ‘λ―Έμ€ κ°μ²΄ μ²λ¦¬
μ΄λ κ² λ§λ€μ΄μ§ Promise κ°μ²΄λ λΉλκΈ° μμ
μ΄ μλ£λ μ΄νμ λ€μ μμ
μ μ°κ²°μμΌ μ§νν μ μλ€. μμ
κ²°κ³Ό λ°λΌ .then() κ³Ό .catch() λ©μλ 체μ΄λμ ν΅ν΄ μ±κ³΅κ³Ό μ€ν¨μ λν νμ μ²λ¦¬λ₯Ό μ§νν μ μλ€.
λ§μΌ μ²λ¦¬κ° μ±κ³΅νμ¬ νλ‘λ―Έμ€ κ°μ²΄ λ΄λΆμμ resolve(data) λ₯Ό νΈμΆνκ² λλ©΄, λ°λ‘ .then() μΌλ‘ μ΄μ΄μ Έ then λ©μλμ μ½λ°± ν¨μμμ μ±κ³΅μ λν μΆκ° μ²λ¦¬λ₯Ό μ§ννλ€. μ΄λ νΈμΆν resolve() ν¨μμ 맀κ°λ³μμ κ°μ΄ then λ©μλμ μ½λ°± ν¨μ μΈμλ‘ λ€μ΄κ° then λ©μλ λ΄λΆμμ νλ‘λ―Έμ€ κ°μ²΄ λ΄λΆμμ λ€λ£¬ κ°μ μ¬μ©ν μ μκ² λλ€.
λ°λλ‘ μ²λ¦¬κ° μ€ν¨νμ¬ νλ‘λ―Έμ€ κ°μ²΄ λ΄λΆμμ reject("Error") λ₯Ό νΈμΆνκ² λλ©΄, λ°λ‘ .catch() λ‘ μ΄μ΄μ Έ catch λ©μλμ μ½λ°± ν¨μμμ μ±κ³΅μ λν μΆκ° μ²λ¦¬λ₯Ό μ§ννλ€.
myPromise
.then((value) => { // μ±κ³΅μ μΌλ‘ μννμ λ μ€νλ μ½λ
console.log("Data: ", value); // μμμ return resolve(data)μ dataκ°μ΄ μΆλ ₯λλ€
})
.catch((error) => { // μ€ν¨νμ λ μ€νλ μ½λ
console.error(error); // μμμ return reject("Error")μ "Error"κ° μΆλ ₯λλ€
})
.finally(() => { // μ±κ³΅νλ μ€ν¨νλ 무쑰건 μ€νλ μ½λ
})
νλ‘λ―Έμ€ ν¨μ λ±λ‘
μμ κ°μ΄ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ³μμ λ°λ‘ ν λΉνλ λ°©μμ μ¬μ©ν μλ μμ§λ§, 보ν΅μ λ€μκ³Ό κ°μ΄ λ³λλ‘ ν¨μλ‘ κ°μΈμ μ¬μ©νλ κ²μ΄ μΌλ°μ μ΄λ€.
// νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ°ννλ ν¨μ μμ±
function myPromise() {
return new Promise((resolve, reject) => {
if (/* μ±κ³΅ 쑰건 */) {
resolve(/* κ²°κ³Ό κ° */);
} else {
reject(/* μλ¬ κ° */);
}
});
}
// νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ°ννλ ν¨μ μ¬μ©
myPromise()
.then((result) => {
// μ±κ³΅ μ μ€νν μ½λ°± ν¨μ
})
.catch((error) => {
// μ€ν¨ μ μ€νν μ½λ°± ν¨μ
});
ν¨μλ₯Ό λ§λ€κ³ κ·Έ ν¨μλ₯Ό νΈμΆνλ©΄ νλ‘λ―Έμ€ μμ±μλ₯Ό return ν¨μΌλ‘μ, 곧λ°λ‘ μμ±λ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό ν¨μ λ°νκ°μΌλ‘ μ»μ΄ μ¬μ©νλ κΈ°λ²μ΄λ€. μ΄λ κ² νλ‘λ―Έμ€ κ°μ²΄λ₯Ό ν¨μλ‘ λ§λλ μ΄μ λ λ€μ 3κ°μ§ μ λκ° μλ€.
- μ¬μ¬μ©μ± : νλ‘λ―Έμ€ κ°μ²΄λ₯Ό ν¨μλ‘ λ§λ€λ©΄ νμν λλ§λ€ νΈμΆνμ¬ μ¬μ©ν¨μΌλ‘μ¨, λ°λ³΅λλ λΉλκΈ° μμ μ ν¨μ¨μ μΌλ‘ μ²λ¦¬ν μ μλ€.
- κ°λ μ± : νλ‘λ―Έμ€ κ°μ²΄λ₯Ό ν¨μλ‘ λ§λ€λ©΄ μ½λμ κ΅¬μ‘°κ° λͺ νμ Έ, λΉλκΈ° μμ μ μ μμ μ¬μ©μ λΆλ¦¬νμ¬ μ½λμ κ°λ μ±μ λμΌ μ μλ€.
- νμ₯μ± : νλ‘λ―Έμ€ κ°μ²΄λ₯Ό ν¨μλ‘ λ§λ€λ©΄ μΈμλ₯Ό μ λ¬νμ¬ λμ μΌλ‘ λΉλκΈ° μμ μ μνν μ μλ€. λν μ¬λ¬ κ°μ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ°ννλ ν¨μλ€μ μ°κ²°νμ¬ λ³΅μ‘ν λΉλκΈ° λ‘μ§μ ꡬνν μ μλ€.
νλ‘λ―Έμ€λ₯Ό μμ±νμ¬ λ°ννλ ν¨μλ₯Ό 'νλ‘λ―Έμ€ ν©ν 리 ν¨μ' λΌκ³ λΆλ¦¬μ°κΈ°λ νλ€.
μ΄λ¬ν μ λλ¬Έμ μ€λ¬΄μμ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό μ¬μ©ν μΌμ΄ μλ€λ©΄ ν¨μλ‘ κ°μΈ μ¬μ©νλ€. κ·Έλμ λλΆλΆμ μλ°μ€ν¬λ¦½νΈ λΉλκΈ° λΌμ΄λΈλ¬λ¦¬λ ν¨μ ννλ‘ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό μ 곡νλ€. λνμ μΌλ‘ μλ°μ€ν¬λ¦½νΈμ fetch() λ©μλκ° μλλ°, μ΄ fetch() λ©μλ λ΄μμ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό μμ±νμ¬ μλ²λ‘λΆν° λ°μ΄ν°λ₯Ό κ°μ Έμ€λ©΄ resolve() νμ¬ .then() μΌλ‘ μ²λ¦¬νκΈ° λλ¬Έμ΄λ€.
// GET μμ² μμ
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => response.json()) // μλ΅ κ°μ²΄μμ JSON λ°μ΄ν°λ₯Ό μΆμΆνλ€.
.then((data) => console.log(data)); // JSON λ°μ΄ν°λ₯Ό μ½μμ μΆλ ₯νλ€.
νλ‘λ―Έμ€ 3κ°μ§ μν
νλ‘λ―Έμ€λ λΉλκΈ° μμ
μ κ²°κ³Όλ₯Ό μ½μνλ κ²μ΄λ€. new Promise() μμ±μλ‘ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό μμ±νλ©΄, κ·Έ λΉλκΈ° μμ
μ μ΄λ―Έ μ§ν μ€μ΄κ³ μΈμ κ°λ μ±κ³΅νκ±°λ μ€ν¨ν κ²μ΄λ€. μ΄λ¬ν μ§νμ€, μ±κ³΅, μ€ν¨ μνλ₯Ό λνλ΄λ κ²μ΄ λ°λ‘ νλ‘λ―Έμ€μ μν(state)λΌκ³ λΆλ¦¬μ΄λ€. μ½κ² λ§νμλ©΄ μΌμ’
μ νλ‘λ―Έμ€ μ²λ¦¬ κ³Όμ μ΄λΌκ³ 보면 λλ€.
- Pending(λκΈ°) : μ²λ¦¬κ° μλ£λμ§ μμ μν (μ²λ¦¬ μ§νμ€)
- Fulfilled(μ΄ν) : μ±κ³΅μ μΌλ‘ μ²λ¦¬κ° μλ£λ μν
- Eejected(κ±°λΆ) : μ²λ¦¬κ° μ€ν¨λ‘ λλ μν
1. Pending μν
λκΈ°(pending) μνλ, λ§ κ·Έλλ‘ μμ§ λΉλκΈ° μ²λ¦¬ λ‘μ§μ΄ μλ£ λμ§ μμ μνμ΄λ€. μλ₯Ό λ€μ΄ μλμ κ°μ΄ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό μμ±νκ³ , μμ±ν νλ‘λ―Έμ€ κ°μ²΄λ₯Ό μ½μμ μ°μ΄λ³΄λ©΄ μλμ κ°μ΄ νλ‘λ―Έμ€ κ°μ²΄μ μνκ° "pending"μΌλ‘ μΆλ ₯λκ² λλ€.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("μ²λ¦¬ μλ£")
}, 5000)
});
console.log(promise); // Pending (λκΈ°) μν
2. Fulfilled μν
μμ νλ‘λ―Έμ€ μ½λλ₯Ό μ€ννκ³ 5μ΄ λμ κΈ°λ€λ¦¬λ€κ° λ€μ μ½μμ μ°μ΄λ³΄μ. κ·ΈλΌ μλμ κ°μ΄ μ΄ν(fulfilled) μνλ‘ λ³νκ² λλ€.
μ¦, 5μ΄κ° μ§λ resolve() μνλλ©΄μ νλ‘λ―Έμ€ μ±κ³΅μ μ리λ κ°μ²΄λ₯Ό νΈμΆ νμμΌλ μ΄ν μνλ‘ λ³ν κ²μ΄λ€. λ°λΌμ μ΄ν(fulfilled) μνλ, λΉλκΈ° μ²λ¦¬ λ‘μ§μ΄ μ±κ³΅μ μΌλ‘ μλ£ λ¬λ€λ κ²μ νννκΈ° μν μνλΌκ³ 보면 λλ€.
νλ‘λ―Έμ€μ 'μ΄ν' μνλ₯Ό λ€λ₯΄κ² νννμλ©΄ 'μλ£' λ΄λ λλ€.
κ·Έλ¦¬κ³ μ΄ν μνλ‘ λ³ν νλ‘λ―Έμ€ κ°μ²΄λ λ°λ‘ 체μ΄λλ .then() λ©μλλ₯Ό νΈμΆνμ¬ μ²λ¦¬ κ²°κ³Ό κ°μ λ°μ μ μλ κ²μ΄λ€.
promise
.then((data) => {
console.log("νλ‘λ―Έμ€κ° μ΄ν μνκ° λλ©΄μ μ²λ¦¬μ λν κ²°κ³Όλ₯Ό μν")
})
3. Rejected μν
resolve()λ₯Ό νΈμΆν¨μΌλ‘μ νλ‘λ―Έμ€ κ°μ²΄ μνκ° μ΄ν(fulfilled) μνκ° λ¬λ€λ©΄, λ°λλ‘ reject()λ₯Ό νΈμΆνλ©΄ νλ‘λ―Έμ€ κ°μ²΄κ° μ€ν¨(rejected) μνκ° λλ€.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("μ²λ¦¬ μ€ν¨")
}, 5000)
});
μμ μ€ν¨ μνλ‘ λ³ν νλ‘λ―Έμ€ κ°μ²΄λ λ°λ‘ 체μ΄λλ .catch() λ©μλλ₯Ό νΈμΆνμ¬ μ²λ¦¬ μ€ν¨μ λν νλμ μννκ² λλ€.
promise
.catch((error) => {
console.log(error);
console.log("μ€ν¨μ λν νμ μ‘°μΉ...")
})
νλ‘λ―Έμ€ νΈλ€λ¬
νλ‘λ―Έμ€κ° μμ±λλ©΄, κ·Έ μμ
μ μ΄λ―Έ μ§ν μ€μ΄κ³ μΈμ κ°λ μ±κ³΅νκ±°λ μ€ν¨ν κ²μ΄λ€. κ·Έ μ±κ³΅/μ€ν¨ κ²°κ³Όλ₯Ό .then / .catch / .finally νΈλ€λ¬λ₯Ό ν΅ν΄ λ°μ λ€μ νμ μμ
μ μνν μ μλ€. νλ‘λ―Έμ€ νΈλ€λ¬λ νλ‘λ―Έμ€μ μνμ λ°λΌ μ€νλλ μ½λ°± ν¨μλΌκ³ 보면 λλ€.
.then(): νλ‘λ―Έμ€κ° μ΄ν(fulfilled)λμμ λ μ€νν μ½λ°± ν¨μλ₯Ό λ±λ‘νκ³ , μλ‘μ΄ νλ‘λ―Έμ€λ₯Ό λ°ν.catch(): νλ‘λ―Έμ€κ° κ±°λΆ(rejected)λμμ λ μ€νν μ½λ°± ν¨μλ₯Ό λ±λ‘νκ³ , μλ‘μ΄ νλ‘λ―Έμ€λ₯Ό λ°ν.finally(): νλ‘λ―Έμ€κ° μ΄νλκ±°λ κ±°λΆλ λ μκ΄μμ΄ μ€νν μ½λ°± ν¨μλ₯Ό λ±λ‘νκ³ , μλ‘μ΄ νλ‘λ―Έμ€λ₯Ό λ°ν
νλ‘λ―Έμ€ νΈλ€λ¬ ꡬμ±μ 보건λ°, λ§μΉ try - catch - finally ꡬ쑰μ κ΅μ₯ν μ μ¬νλ€κ³ λλν
λ° κ·Έ λλμ΄ λ§λ€.
μ΄λ―Έ μμμ νλ‘λ―Έμ€ μνμ λ°λΌ μνλλ νλ‘λ―Έμ€ νΈλ€λ¬ λ¬Έλ²μ λν΄ λ€λ€μΌλ κΈ°λ³Έμ μΈ μ¬μ©λ²μ λ€λ€ μ κ²μ΄λ€. λ€λ§ μ΄ μΉμ μμ μκ°νκ³ μΆμ κ²μ μ΄ νΈλ€λ¬λ€μ 체μ΄λ(chaining) νμ¬ μ΄κ±°νμ¬ λ³΅μ‘νκ² μ¬μ©ν λ μ²λ¦¬ μμμ λν λΆλΆμ΄λ€.
νλ‘λ―Έμ€ μ²΄μ΄λ
νλ‘λ―Έμ€ μ²΄μ΄λμ΄λ, νλ‘λ―Έμ€ νΈλ€λ¬λ₯Ό μ°λ¬μ μ°κ²°νλ κ²μ λ§νλ€. μ΄λ κ² νλ©΄ μ¬λ¬ κ°μ λΉλκΈ° μμ μ μμ°¨μ μΌλ‘ μνν μ μλ€λ νΉμ§μ΄ μλ€.
μλ₯Όλ€μ΄ μλλ doSomething ν¨μλ₯Ό νΈμΆνμ¬ νλ‘λ―Έμ€λ₯Ό μμ±νκ³ , then λ©μλλ₯Ό ν΅ν΄ μ΄ν νΈλ€λ¬λ₯Ό μ°κ²°νλ κ³Όμ μ 보μ¬μ€λ€. κ° μ΄ν νΈλ€λ¬λ μ΄μ νλ‘λ―Έμ€μ κ°μ 50μ λν κ°μ λ°ννκ³ , λ§μ§λ§ μ΄ν νΈλ€λ¬λ μ΅μ’
κ°μ μ½μμ μΆλ ₯νκ² λλ€.
function doSomething() {
return new Promise((resolve, reject) => {
resolve(100)
});
}
doSomething()
.then((value1) => {
const data1 = value1 + 50;
return data1
})
.then((value2) => {
const data2 = value2 + 50;
return data2
})
.then((value3) => {
const data3 = value3 + 50;
return data3
})
.then((value4) => {
console.log(value4); // 250 μΆλ ₯
})
μ΄λ°μμΌλ‘ 체μ΄λμ΄ κ°λ₯ν μ΄μ λ then νΈλ€λ¬μμ κ°μ 리ν΄νλ©΄, κ·Έ λ°νκ°μ μλμΌλ‘ νλ‘λ―Έμ€ κ°μ²΄λ‘ κ°μΈμ Έ λ°νλκΈ° λλ¬Έμ΄λ€. κ·Έλ¦¬κ³ λ€μ then νΈλ€λ¬μμ λ°νλ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ°μ μ²λ¦¬νλ κ²μ΄λ€. κ·Έλμ νλ‘λ―Έμ€ μνμ νλ¦λλ₯Ό νννμλ©΄ μλμ κ°μ΄ λλ€.
λ§μΌ μ°κ²°λ μ΄ν νΈλ€λ¬μμ μ€κ°μ μ€λ₯κ° μλ μ²λ¦¬λ₯Ό ννλ€λ©΄ μμΈμ²λ¦¬λ₯Ό ν¨μΌλ‘μ¨ catch νΈλ€λ¬μ μ ννλλ‘ μ€μ ν μ μλ€. μ΄λ ΅κ² μκ°νμ§ λ§κ³ try - catch μ κ°μ΄ μκ°νλ©΄ λλ€.
function doSomething(arg) {
return new Promise((resolve, reject) => {
resolve(arg)
});
}
doSomething('100A')
.then((value1) => {
const data1 = value1 + 50; // μ«μμ λ¬Έμλ₯Ό μ°μ°
if (isNaN(data1))
throw new Error('κ°μ΄ λλ²κ° μλλλ€')
return data1
})
.then((value2) => {
const data2 = value2 + 50;
return data2
})
.catch((err) => {
console.error(err);
})
λ§μΌ catch νΈλ€λ¬ λ€μμΌλ‘ then νΈλ€λ¬κ° μ΄μ΄μ 체μ΄λ λμ΄ μλ€λ©΄, μλ¬κ° μ²λ¦¬λκ³ κ°κΉμ΄ then νΈλ€λ¬λ‘ μ μ΄ νλ¦μ΄ λμ΄κ° μ€νμ΄ μ΄μ΄μ§κ² λλ€.
new Promise((resolve, reject) => {
throw new Error("μλ¬ λ°μ!");
})
.catch(function(error) {
console.log("μλ¬κ° μ μ²λ¦¬λμμ΅λλ€. μ μμ μΌλ‘ μ€νμ΄ μ΄μ΄μ§λλ€.");
})
.then(() => {
console.log("λ€μ νΈλ€λ¬κ° μ€νλ©λλ€.")
})
.then(() => {
console.log("λ€μ νΈλ€λ¬κ° λ μ€νλ©λλ€.")
});
νλ‘λ―Έμ€ μ μ λ©μλ
νλ‘λ―Έμ€ κ°μ²΄λ μμ±μ ν¨μ μΈμλ μ¬λ¬ κ°μ§ μ μ λ©μλ(static method)λ₯Ό μ 곡νλ€. μ μ λ©μλλ κ°μ²΄λ₯Ό μ΄κΈ°ν & μμ±νμ§ μκ³ λ λ°λ‘ μ¬μ©ν μ μκΈ° λλ¬Έμ λΉλκΈ° μ²λ¦¬λ₯Ό λ³΄λ€ ν¨μ¨μ μ΄κ³ κ°νΈνκ² κ΅¬νν μ μλλ‘ λμμ€λ€.
Promise.resolve()
λ³΄ν΅ νλ‘λ―Έμ€μ resolve() λ©μλλ, νλ‘λ―Έμ€λ₯Ό μμ±μλ‘ λ§λ€κ³ κ·Έμμ μ½λ°± ν¨μμ 맀κ°λ³μλ₯Ό ν΅ν΄ νΈμΆνμ¬ μ¬μ©ν΄μλ€.
// νλ‘λ―Έμ€ μμ±μλ₯Ό μ¬μ©νμ¬ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ°ννλ ν¨μ
function getPromiseNumber() {
return new Promise((resolve, reject) => {
const num = Math.floor(Math.random() * 10); // 0 ~ 9 μ¬μ΄μ μ μ
resolve(num); // νλ‘λ―Έμ€ μ΄ν
});
}
μ΄λ¬ν κ³Όμ μ Promise.resolve() μ μ λ©μλλ‘ νλ²μ νΈμΆν μ μλλ‘ νΈμ κΈ°λ₯μ μ κ³΅ν΄ μ£Όλ κ²μΌλ‘ 보면 λλ€. κ·Έλμ νλ‘λ―Έμ€ μ μ λ©μλλ₯Ό μ΄μ©νλ©΄ νλ‘λ―Έμ€ κ°μ²΄μ μ ν μ°κ΄μλ ν¨μ λ΄μμ νμμ λ°λΌ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ°ννμ¬ νΈλ€λ¬λ₯Ό μ΄μ©ν μ μλλ‘ μμ©μ΄ κ°λ₯νλ€. μ΄ λ°©λ²μ λΉλκΈ° μμ
μ μννμ§ μλ ν¨μμμλ νλ‘λ―Έμ€μ μ₯μ μ νμ©νκ³ μΆμ κ²½μ°μ μ μ©νλ€.
// νλ‘λ―Έμ€ κ°μ²΄μ μ ν μ°κ΄μλ ν¨μ
function getRandomNumber() {
const num = Math.floor(Math.random() * 10); // 0 ~ 9 μ¬μ΄μ μ μ
return num;
}
// Promise.resolve() λ₯Ό μ¬μ©νμ¬ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό λ°ννλ ν¨μ
function getPromiseNumber() {
const num = getRandomNumber(); // μΌλ° κ°
return Promise.resolve(num); // νλ‘λ―Έμ€ κ°μ²΄
}
// νΈλ€λ¬λ₯Ό μ΄μ©νμ¬ νλ‘λ―Έμ€ κ°μ²΄μ κ°μ μ²λ¦¬νλ ν¨μ
getPromiseNumber()
.then((value) => {
console.log(`λλ€ μ«μ: ${value}`);
})
.catch((error) => {
console.error(error);
});
Promise.reject()
λ§μ°¬κ°μ§λ‘ μ£Όμ΄μ§ μ¬μ λ‘ κ±°λΆνλ Promise κ°μ²΄λ₯Ό λ°ννλ€.
// μ£Όμ΄μ§ μ¬μ λ‘ κ±°λΆλλ νλ‘λ―Έμ€ μμ±
const p = Promise.reject(new Error('error'));
// κ±°λΆ μ¬μ λ₯Ό μΆλ ₯
p.catch(error => console.error(error)); // Error: error
Promise.all()
λ°°μ΄, Map, Setμ ν¬ν¨λ μ¬λ¬κ°μ νλ‘λ―Έμ€ μμλ€μ νκΊΌλ²μ λΉλκΈ° μμ μ μ²λ¦¬ν΄μΌ ν λ κ΅μ₯ν μ μ©ν νλ‘λ―Έμ€ μ μ λ©μλμ΄λ€. λͺ¨λ νλ‘λ―Έμ€ λΉλκΈ° μ²λ¦¬κ° μ΄ν(fulfilled) λ λκΉμ§ κΈ°λ€λ €μ, λͺ¨λ νλ‘λ―Έμ€κ° μλ£λλ©΄ κ·Έλ then νΈλ€λ¬κ° μ€ννλ ννλ‘ λ³΄λ©΄ λλ€. κ°μ₯ λνμ μΈ μ¬μ© μμλ‘ μ¬λ¬ κ°μ API μμ²μ 보λ΄κ³ λͺ¨λ μλ΅μ λ°μμΌ νλ κ²½μ°μ μ¬μ©ν μ μλ€.
// 1. μλ² μμ² API νλ‘λ―Έμ€ κ°μ²΄ μμ± (fetch)
const api_1 = fetch("https://jsonplaceholder.typicode.com/users");
const api_2 = fetch("https://jsonplaceholder.typicode.com/users");
const api_3 = fetch("https://jsonplaceholder.typicode.com/users");
// 2. νλ‘λ―Έμ€ κ°μ²΄λ€μ λ¬Άμ΄ λ°°μ΄λ‘ ꡬμ±
const promises = [api_1, api_2, api_3];
// 3. Promise.all() λ©μλ μΈμλ‘ νλ‘λ―Έμ€ λ°°μ΄μ λ£μ΄, λͺ¨λ νλ‘λ―Έμ€κ° μ΄νλ λκΉμ§ κΈ°λ€λ¦¬κ³ , κ²°κ³Όκ°μ μΆλ ₯
Promise.all(promises)
.then((results) => {
// resultsλ μ΄νλ νλ‘λ―Έμ€λ€μ κ°λ€μ λ΄μ λ°°μ΄.
// resultsμ μμλ promisesμ μμμ μΌμΉ.
console.log(results); // [users1, users2, users3]
})
.catch((error) => {
// μ΄λ νλλΌλ νλ‘λ―Έμ€κ° κ±°λΆλλ©΄ μ€λ₯λ₯Ό μΆλ ₯
console.error(error);
});
Promise.allSettled()
Promise.all() λ©μλμ μ
κ·Έλ μ΄λ λ²μ μΌλ‘, μ£Όμ΄μ§ λͺ¨λ νλ‘λ―Έμ€κ° μ²λ¦¬λλ©΄ λͺ¨λ νλ‘λ―Έμ€ κ°κ°μ μνμ κ° (λλ κ±°λΆ μ¬μ )μ λͺ¨μλμ λ°°μ΄μ λ°ννλ€.
// 1μ΄ νμ 1μ λ°ννλ νλ‘λ―Έμ€
const p1 = new Promise(resolve => setTimeout(() => resolve(1), 1000));
// 2μ΄ νμ μλ¬λ₯Ό λ°μμν€λ νλ‘λ―Έμ€
const p2 = new Promise((resolve, reject) => setTimeout(() => reject(new Error('error')), 2000));
// 3μ΄ νμ 3μ λ°ννλ νλ‘λ―Έμ€
const p3 = new Promise(resolve => setTimeout(() => resolve(3), 3000));
// μΈ κ°μ νλ‘λ―Έμ€μ μνμ κ° λλ μ¬μ λ₯Ό μΆλ ₯
Promise.allSettled([p1, p2, p3])
.then(result => console.log(result));
Promise.any()
Promise.all() λ©μλμ λ°λ λ²μ μΌλ‘, Promise.all() μ΄ μ£Όμ΄μ§ λͺ¨λ νλ‘λ―Έμ€κ° λͺ¨λ μλ£ν΄μΌλ§ κ²°κ³Όλ₯Ό λμΆνλ€λ©΄, Promise.any() λ μ£Όμ΄μ§ λͺ¨λ νλ‘λ―Έμ€ μ€ νλλΌλ μλ£λλ©΄ λ°λ‘ λ°ννλ μ μ λ©μλμ΄λ€.
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("promise1 failed");
}, 3000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise2 succeeded");
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("promise3 failed");
}, 1000);
});
// promise1, promise2, promise3μ κ°κ° 3μ΄, 2μ΄, 1μ΄ νμ κ±°λΆλκ±°λ μ΄ν
Promise.any([promise1, promise2, promise3])
.then((value) => {
console.log(value); // "promise2 succeeded"
})
.catch((error) => {
console.error(error);
});
μ μ½λλ₯Ό 보면 Promise.any() λ©μλμ κ²°κ³Όλ‘ promise2μ μ²λ¦¬κ° κ°μ₯ λ¨Όμ λμΆλ¨μ λ³Ό μ μλ€. μ€λ‘μ§ μ²«λ²μ§Έλ‘ μ΄ν(fulfilled) λ νλ‘λ―Έμ€λ§μ μ·¨κΈνκΈ° λλ¬Έμ λλ¨Έμ§ promise1κ³Ό promise3μ κ±°λΆ(rejected)λ 무μλκ² λλ€.
λ§μΌ μμ²λ λͺ¨λ νλ‘λ―Έμ€κ° κ±°λΆ(rejected)λλ©΄, AggregateError κ°μ²΄λ₯Ό μ¬μ λ‘ νλ κ±°λΆ νλ‘λ―Έμ€λ₯Ό λ°ννλ€.
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("promise1 failed");
}, 3000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise2 succeeded");
}, 2000);
});
const promise4 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("promise4 failed");
}, 4000);
});
Promise.any([promise1, promise3, promise4])
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error); // AggregateError: All promises were rejected
console.error(error.errors); // ["promise3 failed", "promise1 failed", "promise4 failed"]
});
Promise.race()
Promise.race() λ Promise.any() μ κ°μ΄ μ¬λ¬ κ°μ νλ‘λ―Έμ€ μ€ κ°μ₯ λ¨Όμ μ²λ¦¬λ νλ‘λ―Έμ€μ κ²°κ³Όκ°μ λ°ννμ§λ§, μ°¨μ΄μ μ΄ μ‘΄μ¬νλ€.
Promise.any()λ κ°μ₯ λ¨Όμ fulfilled(μ΄ν) μνκ° λ νλ‘λ―Έμ€λ§μ λ°ννκ±°λ, νΉμ μ λΆ rejected(μ€ν¨) μνκ°λ νλ‘λ―Έμ€(AggregateError)λ₯Ό λ°ννλ€. λ°λ©΄ Promise.race() λ fulfilled(μ΄ν), rejected(μ€ν¨) μ¬λΆ μκ΄μμ΄ λ¬΄μ‘°κ±΄ μ²λ¦¬κ° λλ νλ‘λ―Έμ€ κ²°κ³Όκ°μ λ°ννλ€.
λ§μΉ νλ‘λ―Έμ€ μ°Έκ°μλ€μ΄ λ μ΄μ±(race) κ²½μ£Όλ₯Ό νλκ²μ λ μ¬λ¦¬λ©΄ λλ€.
μλ μμ μ½λλ₯Ό 보면 μ’ λ μ΄ν΄κ° μμν κ²μ΄λ€.
μ½λ°± μ§μ₯μ μ΄μ νλ‘λ―Έμ€ μ§μ₯
μλ°μ€ν¬λ¦½νΈ νλ‘λ―Έμ€ κ°μ²΄λ₯Ό μ²μ μκ°ν λ μ½λ°± μ§μ₯μ 극볡νλ μ μΈλμ λ¬Έλ²μ΄λΌκ³ μμ μκ² μκ°νμμΌλ©΄μ μ½λ°± μ§μ₯μ μ΄μ νλ‘λ―Έμ€ μ§μ₯(Promise Hell)μ΄λΌλ ν μμλ§ λμ¬ κ²μ΄λ€. κ·Έλ°λ° μ½λ°± λͺ»μ§μκ² νλ‘λ―Έμ€μ then() λ©μλκ° μ§λμΉκ² 체μΈλμ΄ λ°λ³΅λλ©΄ μ½λκ° μ₯ν©ν΄μ§κ³ κ°λ
μ±μ΄ κ΅μ₯ν λ¨μ΄μ§ μ κ° μλ€.
μλ μμ μ½λλ fetch ν¨μλ₯Ό μ¬μ©νμ¬ κΉνλΈ APIμμ μ μ μ 보λ₯Ό κ°μ Έμ€κ³ , then λ©μλλ₯Ό μ¬λ¬ λ² μ°κ²°νμ¬ μ μ λ€μ λ‘κ·ΈμΈ μ΄λ¦μ μΌνλ‘ κ΅¬λΆν λ¬Έμμ΄λ‘ λ§λ€μ΄ μΆλ ₯νλ λΉλκΈ° μμ μ μννλ€. λμ μ체λ λ¬Έμ κ° μμ ν μ§λ§, μ΄λ°μμΌλ‘ thenμ λμ΄λ¨μ΄ λμΌλ©΄ μ½λκ° κΈΈμ΄μ§κ³ , κ° then λ©μλκ° μ΄λ€ κ°μ λ°ννλμ§ νμ νκΈ° μ΄λ ΅κ² λλ€. λν, catch λ©μλκ° λ§μ§λ§μ ν λ²λ§ μ¬μ©λμ΄ μκΈ° λλ¬Έμ, μ€κ°μ λ°μν μ μλ μλ¬λ μμΈ μν©μ λμνκΈ° μ΄λ ΅λ€.
fetch("https://api.github.com/users")
.then((response) => {
if (response.ok) {
return response.json();
} else {
throw new Error("Network Error");
}
})
.then((users) => {
return users.map((user) => user.login);
})
.then((logins) => {
return logins.join(", ");
})
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
μ΄λ₯Ό λλ€μ 극볡νκΈ° μν΄ λμ¨ μλ°μ€ν¬λ¦½νΈμ μ μΈλ λ¬Έλ²μ΄ μλλ° λ°λ‘ async/await ν€μλμ΄λ€. async/await ν€μλλ ES8μμ λμ λ λΉλκΈ° μ²λ¦¬λ₯Ό μν λ¬Έλ²μΌλ‘, νλ‘λ―Έμ€λ₯Ό κΈ°λ°μΌλ‘ νμ§λ§ thenκ³Ό catch λ©μλλ₯Ό μ¬μ©νμ§ μκ³ λΉλκΈ° μμ μ μνν μ μλ€. async/await ν€μλλ₯Ό μ¬μ©νλ©΄ λΉλκΈ° μμ μ λ§μΉ λκΈ° μμ μ²λΌ μΈ μ μμ΄μ μ½λκ° κ°κ²°νκ³ κ°λ μ±μ΄ μ’μμ§κ² λλ€.
try {
const response = await fetch("");
if (response.ok) {
const users = await response.json();
const logins = users.map((user) => user.login);
const result = logins.join(", ");
console.log(result);
} else {
throw new Error("Network Error");
}
} catch (error) {
console.error(error);
}
μ μ μλ νλ‘λ―Έμ€ νΈλ€λ¬λ₯Ό μμ λ²λ¦¬κ³ 1 λΌμΈμΌλ‘ λΉλκΈ° μ½λλ€μ ꡬμ±νμμ λ³Ό μ μλ€. async/await λ¬Έλ²μ λν΄μ μμΈν μ¬μ©λ²μ μλ ν¬μ€ν μ μ°Έκ³ νκΈΈ λ°λλ€.
# μ°Έκ³ μλ£
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://ko.javascript.info/promise-basics
https://velog.io/@ljinsk3/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC-Promise-%EA%B0%9D%EC%B2%B4