Promise, async, await

๐ Promise
โจ new Promise
Promise๋ class์ด๊ธฐ ๋๋ฌธ์ new ํค์๋๋ฅผ ํตํด Promise ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ๋ํ Promise๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ ์ฝ๋ฐฑ ํจ์(executor)๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ฐ ์ด ์ฝ๋ฐฑ ํจ์๋ resolve, reject ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌ๋ฐ๋๋ค.
Promise ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ฉด executor๋ ์๋์ผ๋ก ์คํ๋๊ณ ์์ฑํ๋ ์ฝ๋๋ค์ด ์๋๋๋ค. ์ฝ๋๊ฐ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๋์๋ค๋ฉด resolve ํจ์๋ฅผ ํธ์ถํ๊ณ ์๋ฌ๊ฐ ๋ฐ์ํ์ ๊ฒฝ์ฐ์๋ reject ํจ์๋ฅผ ํธ์ถํ๋ฉด ๋๋ค.
let promise = new Promise((resolve, reject) => {
// 1. ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒฝ์ฐ
// resolve์ ์ธ์์ ๊ฐ์ ์ ๋ฌํ ์๋ ์์ต๋๋ค.
resolve(value);
// 2. ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ
// reject์ ์ธ์์ ์๋ฌ๋ฉ์ธ์ง๋ฅผ ์ ๋ฌํ ์๋ ์์ต๋๋ค.
reject(error);
});
โจ Promise ๊ฐ์ฒด์ ๋ด๋ถ ํ๋กํผํฐ
new Promise๊ฐ ๋ฐํํ๋ Promise ๊ฐ์ฒด๋ state, result ๋ด๋ถ ํ๋กํผํฐ๋ฅผ ๊ฐ๋๋ค. ํ์ง๋ง ์ง์ ์ ๊ทผํ ์ ์๊ณ .then, .catch, .finally ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
โจ State
๊ธฐ๋ณธ ์ํ๋ pending(๋๊ธฐ) ์ ๋๋ค. ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ ์ฝ๋ฐฑ ํจ์(executor)๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ํ๋ค๋ฉด fulfilled (์ดํ)๋ก ๋ณ๊ฒฝ์ด ๋๊ณ , ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ฉด rejected (๊ฑฐ๋ถ)๊ฐ ๋๋ค.
โจ Result
์ฒ์์ undefined ์ด๋ค. ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ ์ฝ๋ฐฑ ํจ์(executor)๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ํ์ฌresolve(value)๊ฐ ํธ์ถ๋๋ฉด value๋ก, ์๋ฌ๊ฐ ๋ฐ์ํ์ฌ reject(error)๊ฐ ํธ์ถ๋๋ฉด error๋ก ๋ณํ๋ค.
๐ then, catch, finally
โจ Then
executor์ ์์ฑํ๋ ์ฝ๋๋ค์ด ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๋์๋ค๋ฉด resolve ํจ์๋ฅผ ํธ์ถํ๊ณ .then ๋ฉ์๋๋ก ์ ๊ทผํ ์ ์๋ค. ๋ํ .then ์์์ ๋ฆฌํดํ ๊ฐ์ด Promise๋ฉด Promise์ ๋ด๋ถ ํ๋กํผํฐ result๋ฅผ ๋ค์ .then ์ ์ฝ๋ฐฑ ํจ์์ ์ธ์๋ก ๋ฐ์์ค๊ณ , Promise๊ฐ ์๋๋ผ๋ฉด ๋ฆฌํดํ ๊ฐ์ .then ์ ์ฝ๋ฐฑ ํจ์์ ์ธ์๋ก ๋ฐ์์ฌ ์ ์๋ค.
let promise = new Promise((resolve, reject) => {
resolve("์ฑ๊ณต");
});
promise.then(value => {
console.log(value);
// "์ฑ๊ณต"
})
โจ Catch
executor์ ์์ฑํ๋ ์ฝ๋๋ค์ด ์๋ฌ๊ฐ ๋ฐ์ํ์ ๊ฒฝ์ฐ์๋ reject ํจ์๋ฅผ ํธ์ถํ๊ณ .catch ๋ฉ์๋๋ก ์ ๊ทผํ ์ ์๋ค.
let promise = new Promise(function(resolve, reject) {
reject(new Error("์๋ฌ"))
});
promise.catch(error => {
console.log(error);
// Error: ์๋ฌ
})
โจ Finally
executor์ ์์ฑํ๋ ์ฝ๋๋ค์ ์ ์ ์ฒ๋ฆฌ ์ฌ๋ถ์ ์๊ด์์ด .finally ๋ฉ์๋๋ก ์ ๊ทผํ ์ ์๋ค.
let promise = new Promise(function(resolve, reject) {
resolve("์ฑ๊ณต");
});
promise
.then(value => {
console.log(value);
// "์ฑ๊ณต"
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log("์ฑ๊ณต์ด๋ ์คํจ๋ ์๋!");
// "์ฑ๊ณต์ด๋ ์คํจ๋ ์๋!"
})
โจ Promise chaining
Promise chaining๊ฐ ํ์ํ๋ ๊ฒฝ์ฐ๋ ๋น๋๊ธฐ ์์ ์ ์์ฐจ์ ์ผ๋ก ์งํํด์ผ ํ๋ ๊ฒฝ์ฐ์ด๋ค. Promise chaining์ด ๊ฐ๋ฅํ ์ด์ ๋ .then, .catch, .finally ์ ๋ฉ์๋๋ค์ Promise๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ผ์ .then์ ํตํด ์ฐ๊ฒฐํ ์ ์๊ณ , ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ .catch ๋ก ์ฒ๋ฆฌํ๋ฉด ๋๋ค.
let promise = new Promise(function(resolve, reject) {
resolve('์ฑ๊ณต');
...
});
promise
.then((value) => {
console.log(value);
return '์ฑ๊ณต';
})
.then((value) => {
console.log(value);
return '์ฑ๊ณต';
})
.then((value) => {
console.log(value);
return '์ฑ๊ณต';
})
.catch((error) => {
console.log(error);
return '์คํจ';
})
.finally(() => {
console.log('์ฑ๊ณต์ด๋ ์คํจ๋ ์๋!');
});
โจ Promise.all()
const promiseOne = () => new Promise((resolve, reject) => setTimeout(() => resolve('1์ด'), 1000));
const promiseTwo = () => new Promise((resolve, reject) => setTimeout(() => resolve('2์ด'), 2000));
const promiseThree = () => new Promise((resolve, reject) => setTimeout(() => resolve('3์ด'), 3000));
Promise.all()์ ์ฌ๋ฌ ๊ฐ์ ๋น๋๊ธฐ ์์ ์ ๋์์ ์ฒ๋ฆฌํ๊ณ ์ถ์๋ ์ฌ์ฉํ๋ค. ์ธ์๋ก๋ ๋ฐฐ์ด์ ๋ฐ๋๋ค. ํด๋น ๋ฐฐ์ด์ ์๋ ๋ชจ๋ Promise์์ executor ๋ด ์์ฑํ๋ ์ฝ๋๋ค์ด ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๋์๋ค๋ฉด ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์ด์ ์ ์ฅํด ์๋ก์ด Promise๋ฅผ ๋ฐํ ํด์ค๋ค.
์์ ๋ฐฐ์ด Promise chaining์ ์ฌ์ฉํ์ ๊ฒฝ์ฐ๋ ์ฝ๋๋ค์ด ์์ฐจ์ ์ผ๋ก ๋์๋๊ธฐ ๋๋ฌธ์ ์ด 6์ด์ ์๊ฐ์ด ๊ฑธ๋ฆฌ๊ฒ ๋๋ค. ๋ํ, ๊ฐ์ ์ฝ๋๊ฐ ์ค๋ณต๋๋ ํ์๋ ๋ฐ์ํ๊ฒ ๋๋ค.
// ๊ธฐ์กด
const result = [];
promiseOne()
.then(value => {
result.push(value);
return promiseTwo();
})
.then(value => {
result.push(value);
return promiseThree();
})
.then(value => {
result.push(value);
console.log(result);
// ['1์ด', '2์ด', '3์ด']
})
์ด๋ฌํ ๋ฌธ์ ๋ค์ Promise.all()์ ํตํด ํด๊ฒฐํ ์ ์๋ค. Promise.all()์ ๋น๋๊ธฐ ์์ ๋ค์ ๋์์ ์ฒ๋ฆฌํ๋ค. ๋ฐ๋ผ์ 3์ด ์์ ๋ชจ๋ ์์ ์ด ์ข ๋ฃ๋๋ค. ๋ํ Promise chaining๋ก ์์ฑํ ์ฝ๋๋ณด๋ค ๊ฐ๊ฒฐํด์ง ๊ฒ์ ํ์ธํ ์ ์๋ค.
// promise.all
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
.then((value) => console.log(value))
// ['1์ด', '2์ด', '3์ด']
.catch((err) => console.log(err));
์ถ๊ฐ์ ์ผ๋ก Promise.all์ ์ธ์๋ก ๋ฐ๋ ๋ฐฐ์ด์ ์๋ Promise ์ค ํ๋๋ผ๋ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ฉด ๋๋จธ์ง Promise์ state์ ์๊ด์์ด ์ฆ์ ์ข ๋ฃ๋๋ค. ์๋์ ์์์ ๊ฐ์ด 1์ด ํ์ ์๋ฌ๊ฐ ๋ฐ์ํ๊ณ Error: ์๋ฌ1์ด ๋ฐํ๋ ํ๋ก๋ ๋ ์ด์ ์๋ํ์ง ์๊ณ ์ข ๋ฃ๋๋ค.
Promise.all([
new Promise((resolve, reject) => setTimeout(() => reject(new Error('์๋ฌ1'))), 1000),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('์๋ฌ2'))), 2000),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('์๋ฌ3'))), 3000),
])
.then((value) => console.log(value))
.catch((err) => console.log(err));
// Error: ์๋ฌ1
โจ async ⇒ ํจ์๋ฅผ ๋น๋๊ธฐ ํจ์๋ก ์ ์ธํ๋ ํค์๋
async function hello() {
return 'Hey guy!';
}
ํจ์๋ฅผ ๋น๋๊ธฐ ํจ์๋ก ์ ์ธํ๋ฉด ํจ์๋ ์๋์ผ๋ก Promise๋ฅผ ๋ฐํํ๋ค.
Promise๋ก ๋ฐํํ๋ผ๊ณ ํ์ง ์์๋ ์๋์ผ๋ก ์์ํ๋ค.
async function hello() {
}
์์ ์ฝ๋์ ๊ฐ์ด hello ๋ผ๋ ๋น๋๊ธฐ ํจ์๋ก ์ ์ธํ์ฌ return์ ๋ฌผ๋ก ์๋ฌด๊ฒ๋ ์์ฑํด ์ฃผ์ง ์์ ์ํ์์ hello() ํธ์ถ ์์ผฐ์ ๋, ์๋์ ๊ฐ์ด ์๋์ผ๋ก Promise๊ฐ ๋จ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด๋, ์์ ๋งํ ๊ฒ๊ณผ ๊ฐ์ด ํจ์๋ ์๋์ผ๋ก Promise๋ฅผ ๋ฐํํ๋ค๋ ๊ฒ์ ์ฆ๋ช ํ๋ค.

const login = async (username, password) => {
if (!username || !password) throw '๊ฑธ์ด๋ด ์์ ๋ ์ด ๋ผ์ด์น...';
if (password === 'antititi') return '์ํฐํฐํฐํฐ!';
throw '๊ฑธ์ด๋ด ์์ ๋ ์ด ๋ผ์ด์น...';
};
login('user', 'antititi')
.then((msg) => {
console.log(`WELCOME! ${msg}`);
})
.catch((e) => {
console.log(`์คํจ... ${e}`);
});

const login = async (username, password) => {
if (!username || !password) throw '๊ฑธ์ด๋ด ์์ ๋ ์ด ๋ผ์ด์น...';
if (password === 'antititi') return '์ํฐํฐํฐํฐ!';
throw '๊ฑธ์ด๋ด ์์ ๋ ์ด ๋ผ์ด์น...';
};
login('user', 'anti')
.then((msg) => {
console.log(`WELCOME! ${msg}`);
})
.catch((e) => {
console.log(`์คํจ... ${e}`);
});

โจ await ⇒ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์ฐ๋ฉด์ ๋๊ธฐ์ ์ผ๋ก ๋ณด์ด๊ฒ ํด ์ค๋ค.
๊ธฐ๋ค๋ฆฌ๊ฒ ํ๋ ๊ฒ! Promise๊ฐ ๊ฐ์ ๋ฐํํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ธฐ ์ํด ๋น๋๊ธฐ ํจ์์ ์คํ์ ์ผ์ ์ ์ง ์ํจ๋ค. ๋น๋๊ธฐ ํจ์์์ ์ ์ฉํ๊ธฐ ๋๋ฌธ์ async์ await๋ ํ์์ด๋ค!