November 14, 2020
async, await μ Promise λ₯Ό μ’ λ κ°κ²°νλ©΄μ κ°νΈνκ² κ·Έλ¦¬κ³ λκΈ°μ μΌλ‘ μ€νλλ κ² μ²λΌ 보μ΄κ² λ§λλ Syntatic Sugar μ΄λ€.
κΈ°μ‘΄μ μ‘΄μ¬νλ Promise λ₯Ό κ°μΈμ λ κ°νΈνκ²,
νλ‘λ―Έμ€μ .then μΌλ‘ μ΄μ΄μ§λ λλ€λ₯Έ Promise Hell μ ν΄κ²°ν΄ μ€ μ μλ λ°©μμ΄κΈ°λ νλ€.
νμ§λ§ 무쑰건 async, await μΌλ‘λ§ promise λ₯Ό λ체ν΄μ μ¬μ©ν΄λΌ λΌλ μλ―Έλ μλλ€.
μμ λͺ¨λ₯΄μ§λ§ μν©μ λ°λΌ promise λ₯Ό μ°κ±°λ νΉμ async, await μ μ°λ κ²μ΄λΌ νλ€.
μ¬μ©μ λ°μ΄ν°λ₯Ό λ°±μλ (μλ²) μμ λ°μμ€λ μν μ νλ fetchUser ν¨μλ₯Ό λ§λ€μ΄ 보μ.
κ·Έλ¦¬κ³ κ·Έ μ½λλ μν μ μννλλ° λλ΅ 10μ΄ μ λ κ±Έλ¦°λ€κ³ κ°μ ν΄ λ³΄μ.
function fetchUser() {
// do network request in 10secs..
return 'GangGunma'
}
const user = fetchUser()
console.log(user)
μ€μ€λ.. 걸리λ μ½λλΌ κ°μ νλ€.
μ΄λ λ― μ€λ 걸리λ μ½λμ λν΄ λΉλκΈ° μ μΌλ‘ λμκ°κ²λ ν΄μ£Όλ μ²λ¦¬λ₯Ό μ ν νμ§ μμμ λ, Javascript Engine μ λκΈ°μ μΌλ‘ μ½λλ₯Ό μννκΈ° λλ¬Έμ,
ν μ€ ν μ€μ΄ λλμΌ λ€μ μ€λ‘ λμ΄κ°λ λκΈ°μ μΈ μ½λλ₯Ό μ²λ¦¬νκΈ° λλ¬Έμ,
fetchUser() λ΄μμ 10μ΄κ° 머무λ₯΄κ³ μλ€κ° κ·Έμ μμΌ βGangGunmaβ κ° λ¦¬ν΄μ΄ λλ€.
κ·Έμ μμΌ λ¦¬ν΄λ κ°μ λ°μ νλ©΄μ μ°νκ² νλ€.
λ§μ½ μμ μ½λ λ€μμ Web νλ©΄μ UI λ₯Ό μ²λ¦¬νλ μ½λκ° μμλ€λ©΄ μΉ νμ΄μ§μ μ μν μ¬μ©μλ 10μ΄ λμ ν ν λΉμ΄μλ νλ©΄μ λ΄μΌλ§ ν κ²μ΄λ€.
λ°λ‘ μ΄λ¬ν μ€λ 걸리λ μ½λ, μΌλ€μ λΉλκΈ° μ μΌλ‘ μ²λ¦¬ν΄ μ£Όμ΄μΌ νλ€!
μλμ κ°μ΄ λ§μ΄λ€! (λκ°κ³ λμΈμμλ€)
function fetchUser() {
return new Promise((resolve, reject) => {
resolve('GangGunma')
})
}
βλ΄κ° μΈμ user μ λ°μ΄ν°λ₯Ό λ°μμ¬μ§ λͺ¨λ₯΄κ² μ§λ§, μ΄ Promise λΌλ Object λ₯Ό κ°μ§κ³ μμΌλ©΄ μ¬κΈ° λ€κ° then μ΄λΌλ μ½λ°±ν¨μλ§ λ±λ‘ν΄ λμΌλ©΄
user μ data κ° μ€λΉλλ λλ‘ λ€κ° λ±λ‘ν μ½λ°±ν¨μλ₯Ό λ΄κ° λΆλ¬μ£Όκ² λ€κ³ μ½μν κ²!β
function fetchUser() {
return new Promise((resolve, reject) => {
return 'GangGunma';
})
}
fetchUser()
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
new Promise κ°μ²΄λ₯Ό 리ν΄νμ§λ§ resolve λ reject λ‘ νΈμΆνμ§ μμκΈ°μ
κ°λ°μλꡬμμ 보λ―μ΄ state κ° κ³μ pending μνμ΄λ€.
κ·Έλμ κΌ Promise μμλ resolve λ reject λ₯Ό μ΄μ©ν΄ μλ£λ₯Ό μ§μ΄μ€μΌ νλ€.
function fetchUser() {
return new Promise((resolve, reject) => {
resolve('GangGunma');
})
}
fetchUser()
Promise {<fulfilled>: "GangGunma"}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "GangGunma"
μ΄μ Promise μνκ° κ°λ°μλꡬμμ fulfilled λ‘ λ°λκ² λλ©΄μ PromiseResult κ° GangGunma λ‘ λ°λ κ±Έ νμΈν μκ° μλ€.
κ·Έλ κ² ν΄μ λ§λ€μ΄λμ Producer λ₯Ό μ¬μ©νλλ‘ consumer λ₯Ό μ€μ ν΄ λ³΄λ©΄,
const user = fetchUser();
user.then(console.log)
GangGunma
Promise {<fulfilled>: undefined}
.then μ΄λΌλ μ½λ°±ν¨μλ₯Ό μ΄μ©ν΄μ μλ²μμ κ°μ μ»μ΄μλ€. μ’μμ’μ λ§μμ λ λ€.
function fetchUser() {
return new Promise((resolve, reject) => {
resolve('GangGunma')
})
}
const user = fetchUser()
user.then(console.log)
μμ κ°μ΄ Promise μ½λλ₯Ό μμ±νμ§ μκ³ λ κ°νΈνκ² λΉλκΈ° μ½λλ₯Ό μμ±νλ λ°©λ²μ΄ μλ€.
μ΄ λΈλ‘κ·Έμ μ£Όμ μ€ μ²«λ²μ§ΈμΈ async λ₯Ό μκ°νλ μκ°μ΄λ€.
async function fetchUser() {
return 'GangGunma';
}
fetchUser()
Promise {<fulfilled>: "GangGunma"}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "GangGunma"
function μμ async λΌλ ν€μλλ§μ μ°λ κ²μΌλ‘ μμ λ§λ€μλ Promise Producer μ λκ°μ κΈ°λ₯μ μννλ€.
λκ°μ΄ fetchUser κ° Promise λ₯Ό 리ν΄νλ€.
async λΌλ ν€μλλ§μΌλ‘ μ½λλΈλμ΄ μλμΌλ‘ Promise λ‘ λ°λκ² λλꡬλ!
κ·Έ κ²°κ³Ό resolve, reject, new Promise ν€μλλ₯Ό μ°μ§ μκ³ λκΈ°μ μΌλ‘ μ½λλ₯Ό μ°λ― λ°λ‘ return ν΄ μ£Όμ΄λ λλꡬλ!
μΌμ μκ°(ms) μ΄ μ§λλ©΄ resolve λ₯Ό νΈμΆνκ² νλ μ§μ° ν¨μμ΄λ€.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
κ·Έλ¦¬κ³ κ°κ° μ¬κ³Όμ λ°λλλ₯Ό 리ν΄νλ Promise λ₯Ό λ§λ€μλ€.
μμ μ§μ° ν¨μ delay(ms) λ₯Ό ν΅ν΄ κ°κ°μ κ³ΌμΌμ λ°λ μκ°μ λλ μ΄ μμΌ μ€κ±΄λ°,
λ°λ‘ μ¬κΈ°μ await μ μ¬μ©νλ€.
async function getApple() {
await delay(3000)
return 'π'
}
async function getBanana() {
await delay(3000)
return 'π'
}
await λ delay(3000) μ΄ λλ λκΉμ§ κΈ°λ€λ € μ€λ€.
μ¦, 3μ΄ μλ€κ° βμ¬κ³Όβ νΉμ βλ°λλβ λ₯Ό 리ν΄νλ Promise λ₯Ό λ§λ€μλ€.
μ¬μ€ μμ μ½λκ° async, await λ₯Ό μ¬μ©νμ§ μμΌλ©΄ μλ μ½λμ²λΌ μΈ μ μλ€.
function getBanana() {
return delay(3000).then(() => 'π')
}
μμ μ½λ 보λ€λ μ΄μ©λ©΄ async, await ν€μλλ₯Ό μ¨μ delay κ° λλ λκΉμ§ κΈ°λ€λ Έλ€κ° banana λ₯Ό 리ν΄νκ² νλ κ²μ΄,
λκΈ°μ μΈ μ½λλ₯Ό μ°λ κ²μ²λΌ 보μ΄κ² ν΄μ κ°λ μ±μ΄ λ μ’μ 보μ΄κΈ°λ νλ€.
μ΄μ λͺ¨λ λ무μμ κ³ΌμΌμ μΉμΈμ΄ ν΄λ³΄μ.
function pickFruits() {
return getApple()
.then(apple => {
return getBanana()
.then(banana => `${apple} + ${banana}`);
})
}
pickFruits().then(console.log)
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
π + π
μ νν 6μ΄ λ€μ (μ¬κ³Ό 3μ΄, λ°λλ 3μ΄) π + π λ‘ λͺ¨λ λ무μμ κ³ΌμΌμ λ° μλ€. (λ°λλκ° λ무μλκ°?)
νμ§λ§ μ½λ°± μ§μ₯μ μ΄μ νλ‘λ―Έμ€ ν¬ μ§μ₯μ μμμ΄λ€. λλ¬΄κ° λ μκΈ΄λ€λ©΄ λμ± μ¬ν μ€μ²©μ μΈ μ²΄μ΄λμ΄ μ΄μ΄μ§ κ²μ΄λ€.
async function pickFruits() {
const apple = await getApple();
const banana = await getBanana();
return `async μ await μ μ¬μ©ν κ³ΌμΌ λ°κΈ° -> ${apple} + ${banana}`;
}
pickFruits().then(console.log)
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
async μ await μ μ¬μ©ν κ³ΌμΌ λ°κΈ° -> π + π
λ§μ°¬κ°μ§λ‘ 6μ΄ λ€μ μ¬κ³Όμ λ°λλλ₯Ό λ°μλ€.
async, await ν€μλλ₯Ό ν΅ν΄ λκΈ°μ μΌλ‘ μ½λλ₯Ό μμ±νλ―μ΄ μμ°μ€λ½κ² μμ±νκ³ , 리ν΄κ°λ μμ°μ€λ½κ² μμ±νλ λ무 κ°νΈν΄ 보μΈλ€.
λ§μ½ async function getApple() μ λ΄λΆ μ½λμ throw βerrorβ κ° μλ€λ©΄,
async function pickFruits() {
try {
const apple = await getApple();
const banana = await getBanana();
} catch() {
// μλ¬ μ²λ¦¬ μ½λ μμ±.
}
return `async μ await μ μ¬μ©ν κ³ΌμΌ λ°κΈ° -> ${apple} + ${banana}`;
}
try, catch λ₯Ό ν΅ν΄ μμ±ν μκ° μλ€.
μλ κ·Όλ° μ¬κ³Ό λ°λκ±° 3μ΄ κΈ°λ€λ¦¬κ³ λ°λλ λ°λκ±° 3μ΄ κΈ°λ€λ¦¬κ³ κΌ μ΄λ κ² ν΄μΌλΌ?
μ¬κ³Όλ λ°λλ λ°λ κ² λ¨Ό μκ΄μ΄λΌκ³ β¦ 6μ΄ κ±Έλ¦¬κ² νλ건 λ무 λΉν¨μ¨μ΄μ§ μλ?
μ¬κ³Ό λ°λλ° 3μ΄, λ°λλλ₯Ό λ°λλ° 3μ΄..
μ΄λ¬ν μμ°¨ μ§νμ λΉν¨μ¨ κ°λ€. μλλ©΄ λ°λλ, μ¬κ³Όλ κ°μ λ°λ νμμμλ μλ‘ μ°κ΄μ΄ μκΈ°μ
μ¬κ³Ό λ€λΈλκΉμ§ λ°λλλ₯Ό λͺ»λ°κ³ κΈ°λ€λ¦΄ νμκ° μ ν μλκ±°λ€.
λ§λ€μ λ§μ λ°λ‘ μ€νλμ΄ λ²λ¦¬λ νλ‘λ―Έμ€μ νΉμ±μ νμ©ν΄ 보μ!
async function pickFruits() {
const applePromise = getApple();
const bananaPromise = getBanana();
// μ¬κ³Όμ λ°λλμ νλ‘λ―Έμ€λ₯Ό λ§λ€μλ€. λ§λ€λ©΄ λ°λ‘ μ€νλλ promise μ νΉμ±μ μ΄μ©!
const apple = await applePromise; // λκΈ°ν μν
const banana = await bananaPromise; // λκΈ°ν μν
return `λ³λ ¬μ μ€ν μ΄μ 3μ΄λ°μ μκ±Έλ¦°λ€! ${apple} + ${banana}`;
}
pickFruits().then(console.log)
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
λ³λ ¬μ μ€ν μ΄μ 3μ΄λ°μ μκ±Έλ¦°λ€! π + π
μ¬κ³Όμ λ°λλμ νλ‘λ―Έμ€λ₯Ό λ§λ€κ³ , λ§λ€λ©΄ λ°λ‘ μ€νλλ νλ‘λ―Έμ€μ νΉμ±μ μ΄μ©ν΄μ μ΄μ λ³λ ¬μ μΌλ‘ μ½λκ° μ€νλκΈ°μ,
λ§λ€μ λ§μ λμμ λ°μ κΈ°λ€λ € λ¨λ€κ° μ¨λ¨Ήλ κ²μ΄λ€.
μ¬κ³Ό 3μ΄ κ·Έλ¦¬κ³ λ°λλ 3μ΄.. 6μ΄κ° 걸리λ κ²μ΄ μλλΌ,
λͺ¨λ λ°λ λ° 3μ΄ κ±Έλ¦¬λ κ²μ΄λ€.
3μ΄ λ§μ λ³λ ¬μ μΌλ‘ μ€ν, μ¦ λμ λ€λ°μ μΌλ‘ κΈ°λ₯μ μννκ² λ§λλ μ μ΄λ€.
νμ§λ§ λ§€μ° λν°ν μ½λμ΄λ€. Promise.all() μ λν΄ μμλ΄μΌ νλ€.
function pickAllFruits() {
return Promise.all([getApple(), getBanana()])
.then(fruits => fruits.join(' + '))
}
pickAllFruits().then(console.log)
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
π + π
Promise.all() μ λ΄λΆ μΈμλ‘ νλ‘λ―Έμ€ λ°°μ΄μ μ λ¬νκ² λλλ° μ΄ λ, λͺ¨λ Promise λ€μ΄ λ³λ ¬μ μΌλ‘ λ€ λ°μμ¬ λκΉμ§ λͺ¨μμ£Όλ μν μ λ΄λΉνλ€.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function getApple() {
await delay(3000)
return 'π'
}
async function getBanana() {
await delay(3000)
return 'π'
}
async function getMelon() {
await delay(1000)
return 'π';
}
function pickOnlyOne() {
return Promise.race([getApple(), getBanana(), getMelon()])
}
pickOnlyOne().then(console.log)
pickOnlyOne().then(console.log)
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
π
Promise.race() λ μΈμλ‘ λ°°μ΄μ μ λ¬λ Promise μ€μμ κ°μ₯ λ¨Όμ κ°μ 리ν΄νλ Promise λ§ μ λ¬μ΄ λμ΄μ§λ€.
1μ΄ λ§μ λ°μ§λ λ©λ‘ μ΄ λ¨Όμ μΆλ ₯λμ΄ λμ¨λ€!