λΉλκΈ° μ²λ¦¬λ₯Ό κ°νΈνκ² νκΈ° μν΄ μ¬μ©λλ, μλ°μ€ν¬λ¦½νΈ λ΄μ₯ μ€λΈμ νΈ
μ ν΄μ§ μ₯μκ°μ κΈ°λ₯μ μννκ³ λμ, μ μμ μΌλ‘ κΈ°λ₯μ΄ μνλλ€λ©΄ μ²λ¦¬λ κ²°κ³Ό κ°μ μ λ¬νκ³ , λ¬Έμ κ° λ°μνλ€λ©΄ μλ¬λ₯Ό μ λ¬νλ€.
ex) λ±λ‘ λ²νΌμ λλ¬ μ΄λ©μΌμ μ λ ₯ν΄ κ²μμ μ¬μ μμ½ ν΄λλ©΄, κ²μμ΄ μ€νλμλ§μ μ΄λ©μΌλ‘ 곡μ§λ₯Ό λ°μ μ μλ€. ννΈ, κ²μμ΄ μ€νλ ν λ±λ‘ λ²νΌμ λλ₯΄λ©΄, μ΄λ―Έ κ²μμ΄ μ€νλ νμ΄λ―λ‘ κΈ°λ€λ¦΄ νμ μμ΄ λ°λ‘ μ΄λ©μΌλ‘ 곡μ§λ₯Ό λ°κ² λλ€.
νλ‘μΈμ€κ° μ²λ¦¬λ₯Ό μν μ€μΈμ§
μνμ΄ μλ£λμ΄ μ±κ³΅νλμ§ μ€ν¨νλμ§
- pending
μ§μ ν μ²λ¦¬λ₯Ό μν μ€μΌ λ- fullfilled
μ²λ¦¬λ₯Ό μ±κ³΅μ μΌλ‘ λλμ λ- rejected
νμΌμ μ°Ύμ μ μκ±°λ λ€νΈμν¬μ λ¬Έμ κ° μκ²Όμ λ
- Producer
μ§μ ν μ²λ¦¬λ₯Ό μννμ¬ λ°μ΄ν°λ₯Ό μ 곡νλ€
μ¬κΈ°μλpromise
κ° ν΄λΉλλ€- Consumer
μνλ λ°μ΄ν°λ₯Ό μλΉνλ€
promiseλ μ°λ¦¬κ° μνλ κΈ°λ₯μ λΉλκΈ°μ μΌλ‘ μννλ€
μ§μ ν μ²λ¦¬λ₯Ό μνν΄ consumerμκ² λ°μ΄ν°λ₯Ό μ 곡νλ producer
μ ν΄λΉνλ€
const promise = new Promise((resolve, reject) => {
// λ³΄ν΅ λ€μ μκ°μ΄ 걸리λ λ¬΄κ±°μ΄ κΈ°λ₯μ μννλ€ (λ€νΈμν¬ ν΅μ , νμΌ μ½μ΄μ€κΈ°)
});
π‘ promiseλ μ€λΈμ νΈμ΄λ―λ‘, Promise μμ±μ ν¨μ
λ₯Ό ν΅ν΄ μμ±ν μ μλ€.
promise μμ±μ ν¨μλ executor
λΌλ μ½λ°± ν¨μλ₯Ό μΈμλ‘ μ λ¬λ°λλ€. executorλ resolve
μ reject
λΌλ 2κ°μ§ μ½λ°± ν¨μλ₯Ό μΈμλ‘ μ λ¬λ°λλ€.
- resolve
κΈ°λ₯μ μ μμ μΌλ‘ μνν ν λ§μ§λ§μ μ΅μ’ λ°μ΄ν°λ₯Ό μ λ¬ν λ νΈμΆλλ€.- reject
κΈ°λ₯μ μννλ€ λ¬Έμ κ° μκΈ°λ©΄ νΈμΆλλ€.
const promise = new Promise((resolve, reject) => {
console.log('doing something...');
});
// console μ°½μ λ°λ‘ μΆλ ₯λλ€.
π‘ κ·Έλ°λ° promiseκ° μμ±λ μκ°, Promise μμ±μ ν¨μμ μΈμλ‘ μ λ¬ν executor(μ½λ°± ν¨μ)κ° λ°λ‘ μ€νλλ€.
λ°λΌμ, λ§μ½ λ€νΈμν¬ μμ²μ μ¬μ©μκ° μꡬνμ λλ§ ν΄μΌ νλ κ²½μ°λΌλ©΄, μ¬μ©μκ° μꡬνμ§λ μμλλ° λΆνμν λ€νΈμν¬ ν΅μ μ΄ μΌμ΄λκ² λλ€. νμ μ΄λ₯Ό μ μν΄μ promiseλ₯Ό μμ±ν΄μΌ νλ€.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('syong');
}, 2000);
});
π‘ setTimeoutμ ν΅ν΄ λ€νΈμν¬ ν΅μ μ νλ κ²μ²λΌ delayλ₯Ό μ€μ μμ κ°μ΄ promiseλ₯Ό μμ±
ν μ μλ€.
promiseλ 2μ΄ λμ μ΄λ€ κΈ°λ₯μ μννλλ°(μ€μ λΌλ©΄ 'μ΄λ€ κΈ°λ₯'μ λ€νΈμν¬ ν΅μ , νμΌ μ½μ΄μ€κΈ° λ±μ΄ ν΄λΉνλ€.)
κ²°κ΅ μ΄λ₯Ό μ±κ³΅μ μΌλ‘ μνν κ²½μ°, resolveλΌλ μ½λ°± ν¨μλ₯Ό νΈμΆνλ€.
resolve ν¨μλ syongμ΄λΌλ λ°μ΄ν°λ₯Ό μ΅μ’
μ μΌλ‘ μ λ¬ν΄μ€λ€.
then, catch, finallyλ₯Ό μ΄μ©ν΄ promiseλ‘λΆν° μνλ λ°μ΄ν°λ₯Ό λ°μμ¬ μ μλ€
μ΄λ€μ promiseλ₯Ό μ΄μ©νλ consumer
μ ν΄λΉνλ€
π‘ promiseμμ κΈ°λ₯μ΄ μ±κ³΅μ μΌλ‘ μνλλ€λ©΄, then()
μ μ΄μ©ν΄ κ·Έ λ°μ΄ν°(value)λ₯Ό λ°μμ μ½λ°± ν¨μλ₯Ό μ€ννλ€.
promise.then(value => {
console.log(value);
});
μ μμ μ κ²½μ°, valueμλ promiseμμ resolve ν¨μλ₯Ό ν΅ν΄ λ°μμ¨ syongμ΄λΌλ λ°μ΄ν°κ° μ λ¬λλ€.
promiseκ° μ±κ³΅μ μΌλ‘ μνλ ν(2μ΄ λ€μ) console μ°½μ syongμ΄ μΆλ ₯λλ€.
π‘ promiseμμ κΈ°λ₯μ μννλ€ λ¬Έμ κ° μκ²Όλ€λ©΄, catch()
λ₯Ό μ΄μ©ν΄ κ·Έ μ€λ₯ λ©μμ§(error)μ λ°μμ μ½λ°± ν¨μλ₯Ό μ€ννλ€.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('syong');
reject(new Error('no network'));
}, 2000);
});
promise
.then(value => { // μ μμ μΌλ‘ κΈ°λ₯ μν μλ£ μ
console.log(value);
})
.catch(error => { // κΈ°λ₯ μν μ€ λ¬Έμ λ°μ μ
console.log(error);
});
μ μ½λλ chainingμ μ΄μ©ν μ½λμ΄λ€.
promise μ€λΈμ νΈμ then() λ©μλλ₯Ό νΈμΆνλ©΄ promise μ€λΈμ νΈλ₯Ό λ°ννλ€.
λ°νλ promiseμ λ€μ catch() λ©μλλ₯Ό νΈμΆν κ²μ΄λ€.
μ μμ μ κ²½μ°, errorμλ promiseμμ reject ν¨μλ₯Ό ν΅ν΄ λ°μμ¨ 'no network'λΌλ μ€λ₯ λ©μμ§κ° μ λ¬λλ€.
promiseκ° κΈ°λ₯ μν μ€ λ¬Έμ κ° λ°μνλ©΄(2μ΄ λ€μ) console μ°½μ no networkκ° μΆλ ₯λλ€.
π‘ finally()
λ promiseκ° κΈ°λ₯ μνμ μ±κ³΅νλ μ€ν¨νλ μκ΄μμ΄, then() νΉμ catch()κ° νΈμΆλ ν, 무쑰건 λ§μ§λ§μ νΈμΆλλ€.
promise
.then(value => {
console.log(value);
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log('finally');
});
// console μ°½ μΆλ ₯ κ²°κ³Ό
// Error: no network
// finally
then() λ©μλλ₯Ό μ΄μ©ν΄ λ€μμ λΉλκΈ° μ²λ¦¬λ€μ λ¬Άμ΄μ μ²λ¦¬
ν μ μλ€.
// μλ²μμ μ«μλ₯Ό λ°μμ€λ(setTimeoutμΌλ‘ λ체) promiseλ₯Ό μμ±νλ€.
const fetchNumber = new promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000);
});
// `then()`μ μ΄μ©ν΄ κ·Έ λ°μ΄ν°(value)λ₯Ό λ°μμ μ½λ°± ν¨μλ₯Ό μ€ννλ€.
// then()μ promiseμ κ°μ μ λ¬ν μλ μκ³ , μλ‘μ΄ promiseλ₯Ό μ λ¬ν μλ μλ€.
fetchNumber
.then(num => num * 2) // then()μ promiseλ‘λΆν° 1μ κ°μ λ°μμ, μ½λ°± ν¨μλ₯Ό μ€νν ν, 2μ κ°μ κ°μ§λ promiseλ₯Ό λ°ννλ€.
.then(num => num * 3) // then()μ promiseλ‘λΆν° 2μ κ°μ λ°μμ, μ½λ°± ν¨μλ₯Ό μ€νν ν, 6μ κ°μ κ°μ§λ promiseλ₯Ό λ°ννλ€.
.then(num => { // then()μ promiseλ‘λΆν° 6μ κ°μ λ°μμ¨ ν, μλ‘μ΄ promiseλ₯Ό λ°ννλ€.
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num - 1), 1000);
// μ«μλ₯Ό λ€λ₯Έ μλ²μ 보λ΄(setTimeoutμΌλ‘ λ체) λ€λ₯Έ μ«μλ‘ λ³νλ κ°μ λ°μμ¨λ€.
// μλ‘μ΄ promiseμ resolve ν¨μλ, 6 - 1μ΄λΌλ κ°μ μ λ¬νλ€.
});
})
.then(num => console.log(num)); // then()μ μλ‘μ΄ promiseλ‘λΆν° 5λΌλ κ°μ λ°μμ, μ΄λ₯Ό μΆλ ₯νλ€.
μλ¬ μν©μ λ°μνκ³ , μλ¬λ₯Ό 볡ꡬνλ κ²μ λ§νλ€
π‘ μλμ getHen, getEgg, cook ν¨μλ, κ°κ° λ€λ₯Έ κ°μ κ°μ§λ promiseλ₯Ό 리ν΄νλ€.
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('π'), 1000);
});
const getEgg = hen =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${hen} => π₯`), 1000);
});
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => π³`), 1000);
});
getHen() // getHen ν¨μλ₯Ό μ€ννμ¬ 'π'μ κ°μΌλ‘ κ°μ§λ promiseλ₯Ό λ§λ λ€.
.then(hen => getEgg(hen)) // 'π'μ΄λΌλ κ°(hen)μ λ°μμ getEgg μ½λ°± ν¨μλ₯Ό μ€νν ν 'π => π₯'μ κ°μΌλ‘ κ°μ§λ promiseλ₯Ό λ°ννλ€.
.then(egg => cook(egg)) // 'π => π₯'μ΄λΌλ κ°(egg)μ λ°μμ cook μ½λ°± ν¨μλ₯Ό μ€νν ν 'π => π₯ => π³'λ₯Ό κ°μΌλ‘ κ°μ§λ promiseλ₯Ό λ°ννλ€.
.then(meal => console.log(meal)); // 'π => π₯ => π³'μ΄λΌλ κ°(meal)μ λ°μμ μ΄λ₯Ό μΆλ ₯νλ€.
νμ΄μ§λ₯Ό μλ‘κ³ μΉ¨ ν ν 3μ΄κ° μ§λλ©΄, console μ°½μ 'π => π₯ => π³'κ° μΆλ ₯λλ€.
π‘ μ΄λ, getEgg ν¨μμμ promiseκ° κΈ°λ₯μ μννλ€κ° λ¬Έμ κ° μκ²Όλ€κ³ κ°μ νμ. getEgg ν¨μμ setTimeout μμ resolve ν¨μλ₯Ό reject ν¨μλ‘ λ°κΏμ λλ€.
const getEgg = hen =>
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error(`error! ${hen} => π₯`)), 1000);
});
μλν λλ‘λΌλ©΄, console μ°½μ reject ν¨μλ₯Ό ν΅ν΄ λ°μμ¨ μ€λ₯ λ©μμ§κ° λ μΌ νλ€.
κ·Έλ¬λ, νμ΄μ§λ₯Ό μλ‘κ³ μΉ¨ ν ν 2μ΄κ° μ§λλ©΄, console μ°½μ μλμ κ°μ μ§μ§ μ€λ₯κ° λ¬λ€.
Uncaught (in promise) Error: error! π => π₯
μ μ€λ₯λ promiseμμ μλ¬κ° μ‘νμ§ μλλ€
λ λ»μ΄λ€.
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ promiseκ° μ±κ³΅μ μΌλ‘ κΈ°λ₯μ μννμ λ μ€νλλ then() λ§κ³ , promiseκ° κΈ°λ₯μ μννλ μ€μ λ¬Έμ κ° λ°μνμ λ μ€νλλ catch()λ₯Ό λ±λ‘ν΄μΌ νλ€.
getHen()
.then(hen => getEgg(hen))
.then(egg => cook(egg))
.then(meal => console.log(meal))
.catch(error => console.log(error));
// getEgg ν¨μμ setTimeout μμ reject ν¨μκ° μ λ¬νλ μ€λ₯ λ©μμ§κ° catch()μ μ λ¬λλ€
λΉλ‘μ console μ°½μ μλμ κ°μ΄, reject ν¨μλ₯Ό ν΅ν΄ λ°μμ¨ μ€λ₯ λ©μμ§κ° λ¨λ κ²μ νμΈν μ μλ€.
Error: error! π => π₯
ννΈ, μμ μλμ μ½λλ κ°λ€.
getHen() .then(getEgg) .then(cook) .then(console.log) .catch(console.log);
π‘ μ μμ λ getEgg ν¨μμμ promiseκ° κΈ°λ₯μ μννλ€κ° λ¬Έμ κ° μκ²Όμ λ, reject ν¨μλ₯Ό ν΅ν΄ λ°μμ¨ μ€λ₯ λ©μμ§λ₯Ό λμμ£Όκ³ , λ μ΄μμ μ½λλ μ€νλμ§ μλ κ²½μ°μ΄λ€.
ννΈ, getEgg ν¨μμμ promiseκ° κΈ°λ₯μ μννλ€κ° λ¬Έμ κ° μκ²Όμ λ, μμ μ€λ₯ λ©μμ§λ₯Ό λ€λ₯Έ κ°μΌλ‘ λ체
νκ³ , λκΉμ§ μ½λκ° μ€νλλλ‘
ν μλ μλ€.
μλ₯Ό λ€μ΄, 'λ¬κ±'μ λ°μμ¬ λ λ¬Έμ κ° μκΈΈ κ²½μ° λ€λ₯Έ μ¬λ£λ‘ λ체νκ³ μΆλ€λ©΄ μλμ κ°μ΄ μ½λλ₯Ό μμ ν μ μλ€.
then(getEgg) λ°λ‘ λ°μ μ°λ¬μ catch()λ₯Ό μ μ΄ λ°λ‘ λ¬Έμ λ₯Ό ν΄κ²°νλλ‘ νλ€.
getHen()
.then(getEgg)
.catch(error => {
return 'π₯';
})
.then(cook)
.then(console.log)
// π₯ => π³
[TIL] 211011 3. μ½λ°± ν¨μ 3) μ½λ°± μ§μ₯ μ°Έκ³
class UserStorage {
loginUser (id, password, onSuccess, onError) {
setTimeout(() => {
if (id === 'syong' && password === 'happy' ||
id === 'corder' && password === 'nice') {
onSuccess(id);
} else {
onError(new Error('not found'));
}
}, 2000);
}
getRoles (user, onSuccess, onError) {
setTimeout(() => {
if (user === 'syong') {
onSuccess({ name: 'syong', role: 'admin' });
} else {
onError(new Error('no access'));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt('idλ₯Ό μ
λ ₯ν΄μ£ΌμΈμ');
const password = prompt('passwordλ₯Ό μ
λ ₯ν΄μ£ΌμΈμ');
// μ½λ°± μ§μ₯
userStorage.loginUser(id, password, user => {
userStorage.getRoles(user, userWithRoles => {
alert(`${userWithRoles.role} ${userWithRoles.name}λ, νμν©λλ€!`);
}, error => {
throw error;
});
}, error => {
throw error;
});
class UserStorage {
loginUser (id, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id === 'syong' && password === 'happy' ||
id === 'corder' && password === 'nice') {
resolve(id);
} else {
reject(new Error('not found'));
}
}, 2000);
});
}
getRoles (user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === 'syong') {
resolve({ name: 'syong', role: 'admin' });
} else {
reject(new Error('no access'));
}
}, 1000);
});
}
}
const userStorage = new UserStorage();
const id = prompt('idλ₯Ό μ
λ ₯ν΄μ£ΌμΈμ');
const password = prompt('passwordλ₯Ό μ
λ ₯ν΄μ£ΌμΈμ');
userStorage.loginUser(id, password)
.then(userStorage.getRoles)
.then(user => alert(`${user.role} ${user.name}λ, νμν©λλ€!`))
.catch(console.log);
promiseλ₯Ό λκΈ°μ μΌλ‘ μ€νλλ κ²μ²λΌ 보μ΄λλ‘ λ§λ€μ΄μ€λ€.
promise chainingμ ν λ, κ³μν΄μ λ€λ₯Έ promiseμ μ°κ²°ν κ²½μ° μ½λκ° λμ‘ν΄μ§ μ μλ€.
μ΄λ asyncμ awaitμ μ΄μ©νλ©΄, μ½λλ₯Ό λκΈ°μμΌλ‘ μ¦, μμλλ‘
λ³΄λ€ κ°λ¨νκ³ κ°νΈνκ² μμ±ν μ μλ€.
λ¨, 무쑰건 asyncμ awaitμΌλ‘ λ°κΏ μ μλ κ²μ μλλ€. κ·Έλλ‘ promiseλ₯Ό μ¨μΌ ν λκ° μλ€. νλ‘μ νΈλ₯Ό ν΄λ³΄λ©΄μ κ°μ μ½νμΌ νλ€.
cf. syntactic sugar(λ¬Έλ²μ μ€ν)
κΈ°μ‘΄μ μ‘΄μ¬νλ κ² μμ νΉμ κΈ°μ‘΄μ μ‘΄μ¬νλ κ²μ κ°μΈμ, μ’ λ μ½κΈ° μ½κ³ μ΄ν΄νκΈ° νΈνλλ‘ λ§λλ κ²μ λ§νλ€.
ex) async, await, class λ±
function fetchUser () {
// 10μ΄μ κ±Έμ³ μλ²λ‘λΆν° λ°μ΄ν°λ₯Ό λ°μμ€λ μ½λκ° μλ€κ³ κ°μ
return 'syong'; // μλ²λ‘λΆν° 'syong'μ΄λΌλ λ°μ΄ν°λ₯Ό λ°μμ΄
}
const user = fetchUser();
console.log(user);
// λ€λ₯Έ μ½λ μλ΅
π‘ μμ κ°μ΄ λκΈ°μμΌλ‘ μμλλ‘ μμ±ν΄μ£Όλ©΄, μ΄ μ½λ λ€μ μμ±λ λ€λ₯Έ μ½λλ€μ, fetchUser ν¨μκ° μ€νλμ΄ syongμ΄λΌλ λ°μ΄ν°λ₯Ό 리ν΄νκΈ°κΉμ§ 10μ΄ λμ μ€νλμ§ λͺ»νλ€.
λ€μ μΉ νμ΄μ§μ UI κ΄λ ¨ μ½λκ° μλ€λ©΄ μ¬μ©μλ 10μ΄ λμ λΉ νμ΄μ§λ§μ λ³΄κ² λλ λ¬Έμ κ° λ°μνλ€. λ°λΌμ μ΄λ₯Ό λΉλκΈ°μ μΌλ‘ μμ ν΄μ€ νμκ° μλ€.
function fetchUser () {
return new Promise((resolve, reject) => {
// 10μ΄μ κ±Έμ³ μλ²λ‘λΆν° λ°μ΄ν°λ₯Ό λ°μμ€λ μ½λ
return 'syong';
});
}
const user = fetchUser();
console.log(user);
π‘ promiseλ₯Ό μμ±ν΄ μ½λλ₯Ό λΉλκΈ°μ μΌλ‘ μμ ν΄μ£Όμλ€. κ·Έλ°λ° μμ μ½λμμλ promiseκ° μνμ μλ£νμ¬ μ±κ³΅ νΉμ μ€ν¨νμ λ μ€νλλ resolveλ rejectλ₯Ό μμ±ν΄μ£Όμ§ μμλ€. κ·Έμ λ°μ΄ν° 'syong'μ return νλ©΄μ λλλ€.
μ΄ κ²½μ°, console μ°½μλ μλμ κ°μ΄ λ¬λ€.
[[PromiseState]]: "pending" // promiseκ° μ§μ ν μ²λ¦¬λ₯Ό κ³μν΄μ μν μ€μ΄λ€
[[PromiseResult]]: undefined // promiseλ μλ²λ‘λΆν° μ΄λ€ λ°μ΄ν°λ λ°μ§ μμλ€.
function fetchUser () {
return new Promise((resolve, reject) => {
// 10μ΄μ κ±Έμ³ μλ²λ‘λΆν° λ°μ΄ν°λ₯Ό λ°μμ€λ μ½λ
resolve('syong');
});
}
const user = fetchUser();
console.log(user);
π‘ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ executor ν¨μ μμμ resolve ν¨μλ₯Ό νΈμΆνλλ‘ μμ νλ€. μ΄μ promiseλ κΈ°λ₯μ μ μμ μΌλ‘ μνν ν μ΅μ’ λ°μ΄ν°λ₯Ό μ λ¬νκ³ μ resolveλ₯Ό νΈμΆνλ€.
μ΄ κ²½μ°, console μ°½μλ μλμ κ°μ΄ λ¬λ€.
[[PromiseState]]: "fulfilled" // promiseκ° μ§μ ν μ²λ¦¬λ₯Ό μ±κ³΅μ μΌλ‘ μλ£νλ€
[[PromiseResult]]: "syong" // promiseμ syongμ΄λΌλ λ°μ΄ν°λ₯Ό μ λ¬νλ€.
async function fetchUser () {
// 10μ΄μ κ±Έμ³ μλ²λ‘λΆν° λ°μ΄ν°λ₯Ό λ°μμ€λ μ½λ
return 'syong';
}
const user = fetchUser();
console.log(user);
// λ€λ₯Έ μ½λ μλ΅
π‘ ννΈ, ν¨μ μμ asyncλ₯Ό μΆκ°
νλ©΄ ν¨μμ μ½λ λΈλμ΄ μλμΌλ‘ promiseλ‘ λ°λλ€. μ΄ κ²½μ°μ μ½λλ₯Ό λκΈ°μμΌλ‘ μ¦, μμλλ‘ μμ±νλλΌλ μ²λ¦¬λ λΉλκΈ°μ μΌλ‘ μ΄λ€μ§λ€.
λ°λΌμ, promiseκ° μ§μ λ μ²λ¦¬λ₯Ό μννλ λμ, μ΄ μ½λ λ€μ μμ±λ λ€λ₯Έ μ½λλ€λ promiseκ° μ²λ¦¬λ₯Ό μλ£λ λκΉμ§ κΈ°λ€λ¦΄ νμ μμ΄, ν¨κ» μ€νλλ€.