์ด ๊ธฐ์ฌ์ ์ ์๋ JavaScript์์ Async/Await์ ์๋ฅผ ๊ฒํ ํฉ๋๋ค. ์ ๋ฐ์ ์ผ๋ก Async/Await๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์
๋๋ค. ์ด ๊ธฐ๋ฅ์ด ๋ํ๋๊ธฐ ์ ์๋ ์ฝ๋ฐฑ๊ณผ ํ๋ผ๋ฏธ์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฌํ ์ฝ๋๊ฐ ์์ฑ๋์์ต๋๋ค. ์๋ฌธ์ ์ ์๋ ๋ค์ํ ์์๋ฅผ ๋ถ์ํ์ฌ Async/Await์ ์ฅ์ ์ ๋ฐํ๋์ต๋๋ค.
์๋ฆผ: "Habr"์ ๋ชจ๋ ๋ ์๋ฅผ ์ํ - "Habr" ํ๋ก๋ชจ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ Skillbox ๊ณผ์ ์ ๋ฑ๋กํ ๋ 10 ๋ฃจ๋ธ ํ ์ธ.
Skillbox๋ ๋ค์์ ๊ถ์ฅํฉ๋๋ค. ๊ต์ก์ฉ ์จ๋ผ์ธ ๊ณผ์
"์๋ฐ ๊ฐ๋ฐ์" .
์ฝ๋ฐฑ
์ฝ๋ฐฑ์ ํธ์ถ์ด ๋ฌดํ์ ์ง์ฐ๋๋ ํจ์์ ๋๋ค. ์ด์ ์๋ ๊ฒฐ๊ณผ๋ฅผ ์ฆ์ ์ป์ ์ ์๋ ์ฝ๋ ์์ญ์์ ์ฝ๋ฐฑ์ด ์ฌ์ฉ๋์์ต๋๋ค.
๋ค์์ Node.js์์ ํ์ผ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฝ๋ ์์ ๋๋ค.
fs.readFile(__filename, 'utf-8', (err, data) => {
if (err) {
throw err;
}
console.log(data);
});
์ฌ๋ฌ ๋น๋๊ธฐ ์์
์ ๋์์ ์ํํด์ผ ํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. Arfat ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ํ ์์ฒญ์ด ์ด๋ฃจ์ด์ง๋ฉด ํด๋น profile_img_url ํ๋๋ฅผ ์ฝ๊ณ someserver.com ์๋ฒ์์ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ก๋ํด์ผ ํ๋ ์๋๋ฆฌ์ค๋ฅผ ์์ํด ๋ด
์๋ค.
๋ค์ด๋ก๋ ํ ์ด๋ฏธ์ง๋ฅผ ๋ค๋ฅธ ํ์(์: PNG์์ JPEG๋ก ๋ณํ)์ผ๋ก ๋ณํํฉ๋๋ค. ๋ณํ์ด ์ฑ๊ณตํ๋ฉด ์ฌ์ฉ์์ ์ด๋ฉ์ผ๋ก ํธ์ง๊ฐ ์ ์ก๋ฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ด๋ฒคํธ์ ๋ํ ์ ๋ณด๊ฐ ๋ณํ.log ํ์ผ์ ์
๋ ฅ๋์ด ๋ ์ง๋ฅผ ํ์ํฉ๋๋ค.
์ฝ๋์ ๋ง์ง๋ง ๋ถ๋ถ์ ์๋ ์ฝ๋ฐฑ์ ์ค๋ณต๊ณผ ๋ง์ ์์ })์ ์ฃผ์ํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ์ฝ๋ฐฑ ์ง์ฅ(Callback Hell) ๋๋ ํ๋ฉธ์ ํผ๋ผ๋ฏธ๋(Pyramid of Doom)๋ผ๊ณ ํฉ๋๋ค.
์ด ๋ฐฉ๋ฒ์ ๋จ์ ์ ๋ช ๋ฐฑํฉ๋๋ค.
- ์ด ์ฝ๋๋ ์ฝ๊ธฐ ์ด๋ ต์ต๋๋ค.
- ๋ํ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ค์ ์ฝ๋ ํ์ง์ด ์ ํ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด JavaScript์ Promise๊ฐ ์ถ๊ฐ๋์์ต๋๋ค. ์ฝ๋ฐฑ์ ๊น์ ์ค์ฒฉ์ .then์ด๋ผ๋ ๋จ์ด๋ก ๋ฐ๊ฟ ์ ์์ต๋๋ค.
Promise์ ๊ธ์ ์ ์ธ ์ธก๋ฉด์ ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ด ์๋ ์์์ ์๋๋ก ์ฝ๋๋ฅผ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ ๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ Promise์๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
- .then์ ๋ง์ด ์ถ๊ฐํด์ผ ํฉ๋๋ค.
- try/catch ๋์ .catch๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
- ํ๋์ ๋ฃจํ ๋ด์์ ์ฌ๋ฌ Promise๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํญ์ ํธ๋ฆฌํ ๊ฒ์ ์๋๋ฉฐ ์ด๋ค ๊ฒฝ์ฐ์๋ ์ฝ๋๊ฐ ๋ณต์กํด์ง๋๋ค.
๋ง์ง๋ง ์์ ์ ์๋ฏธ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ฌด์์ ๊ฐ๊ฒฉ(0~n์ด)์ผ๋ก 10๋ถํฐ 0๊น์ง์ ์ซ์ ์ํ์ค๋ฅผ ์ธ์ํ๋ for ๋ฃจํ๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. promise๋ฅผ ์ฌ์ฉํ๋ฉด ์ซ์๊ฐ 0๋ถํฐ 10๊น์ง ์์๋๋ก ์ธ์๋๋๋ก ์ด ๋ฃจํ๋ฅผ ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ 6์ ์ธ์ํ๋ ๋ฐ 2์ด๊ฐ ๊ฑธ๋ฆฌ๊ณ XNUMX์ ์ธ์ํ๋ ๋ฐ XNUMX์ด๊ฐ ๊ฑธ๋ฆฌ๋ฉด XNUMX์ด ๋จผ์ ์ธ์๋๊ณ ๊ทธ ๋ค์์๋ XNUMX์ด ์ธ์๋ฉ๋๋ค. ์ธ์ ์นด์ดํธ๋ค์ด์ด ์์๋ฉ๋๋ค.
๋ฌผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Async/Await ๋๋ .sort๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค. ์์ ์๋ฃจ์ ์ ๋์ ์์ต๋๋ค.
๋น๋๊ธฐ ๊ธฐ๋ฅ
ES2017(ES8)์ ๋น๋๊ธฐ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋๋ฉด์ Promise ์์ ์์ ์ด ๋จ์ํ๋์์ต๋๋ค. ๋น๋๊ธฐ ํจ์๋ Promise์ "์์"์์ ์๋ํ๋ค๋ ์ ์ ์ฃผ๋ชฉํฉ๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ ์ง์ ์ผ๋ก ๋ค๋ฅธ ๊ฐ๋ ์ ๋ํ๋ด์ง ์์ต๋๋ค. ๋น๋๊ธฐ ํจ์๋ ์ฝ์์ ์ฌ์ฉํ๋ ์ฝ๋์ ๋์์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
Async/Await๋ฅผ ์ฌ์ฉํ๋ฉด ๋น๋๊ธฐ ์ฝ๋๋ก ์์ ์ ๋๊ธฐ ์คํ์ผ๋ก ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ Promise๋ฅผ ์๋ฉด Async/Await์ ์๋ฆฌ๋ฅผ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์์ต๋๋ค.
๊ตฌ๋ฌธ
์ผ๋ฐ์ ์ผ๋ก async์ wait๋ผ๋ ๋ ๊ฐ์ ํค์๋๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ฒซ ๋ฒ์งธ ๋จ์ด๋ ํจ์๋ฅผ ๋น๋๊ธฐ์์ผ๋ก ๋ฐ๊ฟ๋๋ค. ์ด๋ฌํ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ธฐ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ ์ธ์ ๊ฒฝ์ฐ์๋ ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
// With function declaration
async function myFn() {
// await ...
}
// With arrow function
const myFn = async () => {
// await ...
}
function myFn() {
// await fn(); (Syntax Error since no async)
}
Async๋ ํจ์ ์ ์ธ์ ๋งจ ์ฒ์์ ์ฝ์ ๋๋ฉฐ, ํ์ดํ ํจ์์ ๊ฒฝ์ฐ "=" ๊ธฐํธ์ ๊ดํธ ์ฌ์ด์ ์ฝ์ ๋ฉ๋๋ค.
์ด๋ฌํ ํจ์๋ ๊ฐ์ฒด์ ๋ฉ์๋๋ก ๋ฐฐ์น๋๊ฑฐ๋ ํด๋์ค ์ ์ธ์ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
// As an object's method
const obj = {
async getName() {
return fetch('https://www.example.com');
}
}
// In a class
class Obj {
async getResource() {
return fetch('https://www.example.com');
}
}
์ฃผ์! ํด๋์ค ์์ฑ์์ getter/setter๋ ๋น๋๊ธฐ์ ์ผ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํด ๋๋ ๊ฒ์ด ์ข์ต๋๋ค.
์๋ฏธ๋ก ๋ฐ ์คํ ๊ท์น
๋น๋๊ธฐ ํจ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ค JS ํจ์์ ์ ์ฌํ์ง๋ง ์์ธ๊ฐ ์์ต๋๋ค.
๋ฐ๋ผ์ ๋น๋๊ธฐ ํจ์๋ ํญ์ ์ฝ์์ ๋ฐํํฉ๋๋ค.
async function fn() {
return 'hello';
}
fn().then(console.log)
// hello
ํนํ fn์ hello ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค. ์, ์ด๊ฒ์ ๋น๋๊ธฐ ํจ์์ด๊ธฐ ๋๋ฌธ์ ๋ฌธ์์ด ๊ฐ์ ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ Promise์ ๋ํ๋ฉ๋๋ค.
๋น๋๊ธฐ๊ฐ ์๋ ๋์ฒด ๋์์ธ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
function fn() {
return Promise.resolve('hello');
}
fn().then(console.log);
// hello
์ด ๊ฒฝ์ฐ Promise๋ "์๋์ผ๋ก" ๋ฐํ๋ฉ๋๋ค. ๋น๋๊ธฐ ํจ์๋ ํญ์ ์๋ก์ด Promise๋ก ๋ํ๋ฉ๋๋ค.
๋ฐํ ๊ฐ์ด ํ๋ฆฌ๋ฏธํฐ๋ธ์ธ ๊ฒฝ์ฐ ๋น๋๊ธฐ ํจ์๋ ๊ฐ์ Promise๋ก ๋ํํ์ฌ ๋ฐํํฉ๋๋ค. ๋ฐํ ๊ฐ์ด Promise ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ ํด๋น ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์ Promise๋ก ๋ฐํ๋ฉ๋๋ค.
const p = Promise.resolve('hello')
p instanceof Promise;
// true
Promise.resolve(p) === p;
// true
ํ์ง๋ง ๋น๋๊ธฐ ํจ์ ๋ด๋ถ์ ์ค๋ฅ๊ฐ ์์ผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
async function foo() {
throw Error('bar');
}
foo().catch(console.log);
์ฒ๋ฆฌ๋์ง ์์ผ๋ฉด foo()๋ ๊ฑฐ๋ถ๋ Promise๋ฅผ ๋ฐํํฉ๋๋ค. ์ด ์ํฉ์์๋ Promise.resolve ๋์ ์ค๋ฅ๊ฐ ํฌํจ๋ Promise.reject๊ฐ ๋ฐํ๋ฉ๋๋ค.
๋น๋๊ธฐ ํจ์๋ ๋ฐํ๋๋ ๋ด์ฉ์ ๊ด๊ณ์์ด ํญ์ Promise๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
๋น๋๊ธฐ ํจ์๋ ๋๊ธฐํ ๋๋ง๋ค ์ผ์ ์ค์ง๋ฉ๋๋ค.
Wait๋ ํํ์์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ๋ฐ๋ผ์ ํํ์์ด ์ฝ์์ธ ๊ฒฝ์ฐ ์ฝ์์ด ์ดํ๋ ๋๊น์ง ๋น๋๊ธฐ ํจ์๊ฐ ์ผ์ ์ค์ง๋ฉ๋๋ค. ํํ์์ด Promise๊ฐ ์๋ ๊ฒฝ์ฐ Promise.resolve๋ฅผ ํตํด Promise๋ก ๋ณํ๋ ํ ์๋ฃ๋ฉ๋๋ค.
// utility function to cause delay
// and get random value
const delayAndGetRandom = (ms) => {
return new Promise(resolve => setTimeout(
() => {
const val = Math.trunc(Math.random() * 100);
resolve(val);
}, ms
));
};
async function fn() {
const a = await 9;
const b = await delayAndGetRandom(1000);
const c = await 5;
await delayAndGetRandom(1000);
return a + b * c;
}
// Execute fn
fn().then(console.log);
๋ค์์ fn ํจ์์ ์๋ ๋ฐฉ์์ ๋ํ ์ค๋ช ์ ๋๋ค.
- ์ด๋ฅผ ํธ์ถํ ํ ์ฒซ ๋ฒ์งธ ์ค์ const a = wait 9;์์ ๋ณํ๋ฉ๋๋ค. const a = Promise.resolve(9);๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค.
- Await๋ฅผ ์ฌ์ฉํ ํ์๋ a๊ฐ ํด๋น ๊ฐ์ ์ป์ ๋๊น์ง(ํ์ฌ ์ํฉ์์๋ 9์) ํจ์ ์คํ์ด ์ผ์ ์ค์ง๋ฉ๋๋ค.
- DelayAndGetRandom(1000)์ fn ํจ์๊ฐ ์์ฒด์ ์ผ๋ก ์๋ฃ๋ ๋๊น์ง(1์ด ํ) fn ํจ์์ ์คํ์ ์ผ์ ์ค์งํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด fn ๊ธฐ๋ฅ์ด 1์ด ๋์ ํจ๊ณผ์ ์ผ๋ก ์ค์ง๋ฉ๋๋ค.
- ํด๊ฒฐ์ ํตํด DelayAndGetRandom(1000)์ ์์์ ๊ฐ์ ๋ฐํํ ๋ค์ ๋ณ์ b์ ํ ๋น๋ฉ๋๋ค.
- ์, ๋ณ์ c์ ๊ฒฝ์ฐ๋ ๋ณ์ a์ ๊ฒฝ์ฐ์ ์ ์ฌํฉ๋๋ค. ๊ทธ ํ ๋ชจ๋ ๊ฒ์ด ์ ์ ์ค์ง๋์ง๋ง ์ด์ ํ์ํ์ง ์๊ธฐ ๋๋ฌธ์ DelayAndGetRandom(1000)์ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์ต๋๋ค.
- ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ฐ์ a + b * c ๊ณต์์ ์ฌ์ฉํ์ฌ ๊ณ์ฐ๋ฉ๋๋ค. ๊ฒฐ๊ณผ๋ Promise.resolve๋ฅผ ์ฌ์ฉํ์ฌ Promise๋ก ๋ํ๋๊ณ ํจ์์ ์ํด ๋ฐํ๋ฉ๋๋ค.
์ด๋ฌํ ์ผ์ ์ค์ง๋ ES6์ ์์ฑ๊ธฐ๋ฅผ ์ฐ์์ํฌ ์ ์์ง๋ง ์ฌ๊ธฐ์๋ ๋ญ๊ฐ๊ฐ ์์ต๋๋ค.
๋ฌธ์ ํด๊ฒฐ
์, ์ด์ ์์์ ์ธ๊ธํ ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
FinishMyTask ํจ์๋ Await๋ฅผ ์ฌ์ฉํ์ฌ queryDatabase, sendEmail, logTaskInFile ๋ฑ๊ณผ ๊ฐ์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค. ์ด ์๋ฃจ์ ์ Promise๊ฐ ์ฌ์ฉ๋ ์๋ฃจ์ ๊ณผ ๋น๊ตํด ๋ณด๋ฉด ์ ์ฌ์ ์ด ๋ถ๋ช ํด์ง ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ Async/Await ๋ฒ์ ์ ๋ชจ๋ ๊ตฌ๋ฌธ ๋ณต์ก์ฑ์ ํฌ๊ฒ ๋จ์ํํฉ๋๋ค. ์ด ๊ฒฝ์ฐ .then/.catch์ ๊ฐ์ ์ฝ๋ฐฑ ๋ฐ ์ฒด์ธ ์๊ฐ ๋ง์ง ์์ต๋๋ค.
๋ค์์ ์ซ์๋ฅผ ์ถ๋ ฅํ๋ ์๋ฃจ์ ์ ๋๋ค. ๋ ๊ฐ์ง ์ต์ ์ด ์์ต๋๋ค.
const wait = (i, ms) => new Promise(resolve => setTimeout(() => resolve(i), ms));
// Implementation One (Using for-loop)
const printNumbers = () => new Promise((resolve) => {
let pr = Promise.resolve(0);
for (let i = 1; i <= 10; i += 1) {
pr = pr.then((val) => {
console.log(val);
return wait(i, Math.random() * 1000);
});
}
resolve(pr);
});
// Implementation Two (Using Recursion)
const printNumbersRecursive = () => {
return Promise.resolve(0).then(function processNextPromise(i) {
if (i === 10) {
return undefined;
}
return wait(i, Math.random() * 1000).then((val) => {
console.log(val);
return processNextPromise(i + 1);
});
});
};
๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์ ๋น๋๊ธฐ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ์๋ฃจ์ ์ด ์์ต๋๋ค.
async function printNumbersUsingAsync() {
for (let i = 0; i < 10; i++) {
await wait(i, Math.random() * 1000);
console.log(i);
}
}
์ค๋ฅ ์ฒ๋ฆฌ
์ฒ๋ฆฌ๋์ง ์์ ์ค๋ฅ๋ ๊ฑฐ๋ถ๋ Promise๋ก ๋ํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋น๋๊ธฐ ํจ์๋ try/catch๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ฅ๋ฅผ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
async function canRejectOrReturn() {
// wait one second
await new Promise(res => setTimeout(res, 1000));
// Reject with ~50% probability
if (Math.random() > 0.5) {
throw new Error('Sorry, number too big.')
}
return 'perfect number';
}
canRejectOrReturn()์ ์ฑ๊ณต("์๋ฒฝํ ์ซ์")ํ๊ฑฐ๋ ์ค๋ฅ("์ฃ์กํฉ๋๋ค. ์ซ์๊ฐ ๋๋ฌด ํฝ๋๋ค")์ ํจ๊ป ์คํจํ๋ ๋น๋๊ธฐ ํจ์์ ๋๋ค.
async function foo() {
try {
await canRejectOrReturn();
} catch (e) {
return 'error caught';
}
}
์์ ์์์๋ canRejectOrReturn์ด ์คํ๋ ๊ฒ์ผ๋ก ์์ํ๋ฏ๋ก ์์ฒด ์คํจ๋ก ์ธํด catch ๋ธ๋ก์ด ์คํ๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก foo ํจ์๋ ์ ์๋์ง ์์ ์ํ(try ๋ธ๋ก์์ ์๋ฌด๊ฒ๋ ๋ฐํ๋์ง ์์ ๊ฒฝ์ฐ) ๋๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ํ๋ก ์ข ๋ฃ๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก try/catch๊ฐ foo ํจ์ ์์ฒด๋ฅผ ์ฒ๋ฆฌํ๋ฏ๋ก ์ด ํจ์๋ ์คํจํ์ง ์์ต๋๋ค.
๋ค์์ ๋ ๋ค๋ฅธ ์์ ๋๋ค.
async function foo() {
try {
return canRejectOrReturn();
} catch (e) {
return 'error caught';
}
}
์ด ์์์ canRejectOrReturn์ด foo์์ ๋ฐํ๋๋ค๋ ์ฌ์ค์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ Foo๋ ์์ ์๋ก ์ข ๋ฃ๋๊ฑฐ๋ ์ค๋ฅ("์ฃ์กํฉ๋๋ค. ์ซ์๊ฐ ๋๋ฌด ํฝ๋๋ค")๋ฅผ ๋ฐํํฉ๋๋ค. catch ๋ธ๋ก์ ์ ๋ ์คํ๋์ง ์์ต๋๋ค.
๋ฌธ์ ๋ foo๊ฐ canRejectOrReturn์์ ์ ๋ฌ๋ Promise๋ฅผ ๋ฐํํ๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ foo์ ๋ํ ์๋ฃจ์ ์ canRejectOrReturn์ ๋ํ ์๋ฃจ์ ์ด ๋ฉ๋๋ค. ์ด ๊ฒฝ์ฐ ์ฝ๋๋ ๋ค์ ๋ ์ค๋ก๋ง ๊ตฌ์ฑ๋ฉ๋๋ค.
try {
const promise = canRejectOrReturn();
return promise;
}
Wait์ Return์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ด๋ค ์ผ์ด ๋ฐ์ํฉ๋๊น?
async function foo() {
try {
return await canRejectOrReturn();
} catch (e) {
return 'error caught';
}
}
์์ ์ฝ๋์์ foo๋ ์์ ์์ ์ค๋ฅ๊ฐ ๋ฐ๊ฒฌ๋ ์ํ๋ก ์ฑ๊ณต์ ์ผ๋ก ์ข ๋ฃ๋ฉ๋๋ค. ์ฌ๊ธฐ์๋ ๊ฑฐ์ ์ด ์์ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ foo๋ ์ ์๋์ง ์์ ์ํ๊ฐ ์๋ canRejectOrReturn์ผ๋ก ๋ฐํ๋ฉ๋๋ค. return wait canRejectOrReturn() ํ์ ์ ๊ฑฐํ์ฌ ์ด๋ฅผ ํ์ธํ๊ฒ ์ต๋๋ค.
try {
const value = await canRejectOrReturn();
return value;
}
// โฆ
์ผ๋ฐ์ ์ธ ์ค์์ ํจ์
๊ฒฝ์ฐ์ ๋ฐ๋ผ Async/Await๋ฅผ ์ฌ์ฉํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
์ํ์ง ๊ธฐ๋ค๋ฆผ
์ด๋ฐ ์ผ์ด ์์ฃผ ๋ฐ์ํฉ๋๋ค. ์ฝ์ ์ ์ wait ํค์๋๋ฅผ ์์ด๋ฒ๋ฆฌ๊ฒ ๋ฉ๋๋ค.
async function foo() {
try {
canRejectOrReturn();
} catch (e) {
return 'caught';
}
}
๋ณด์๋ค์ํผ ์ฝ๋์๋ ๋๊ธฐ ๋๋ ๋ฐํ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ foo๋ ํญ์ 1์ด์ ์ง์ฐ ์์ด undefound๋ก ์ข ๋ฃ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ ์ฝ์์ ์ฑ์ทจ๋ ๊ฒ์ ๋๋ค. ์ค๋ฅ๋ ๊ฑฐ๋ถ๊ฐ ๋ฐ์ํ๋ฉด UnhandledPromiseRejectionWarning์ด ํธ์ถ๋ฉ๋๋ค.
์ฝ๋ฐฑ์ ๋น๋๊ธฐ ํจ์
๋น๋๊ธฐ ํจ์๋ .map ๋๋ .filter์์ ์ฝ๋ฐฑ์ผ๋ก ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด GitHub์์ ์ด๋ฆฐ ๋ฆฌํฌ์งํ ๋ฆฌ ์๋ฅผ ๋ฐํํ๋ fetchPublicReposCount(username) ํจ์๊ฐ ์์ต๋๋ค. ์ธก์ ํญ๋ชฉ์ด ํ์ํ ์ธ ๋ช ์ ์ฌ์ฉ์๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์ด ์์ ์ ๋ํ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
const url = 'https://api.github.com/users';
// Utility fn to fetch repo counts
const fetchPublicReposCount = async (username) => {
const response = await fetch(`${url}/${username}`);
const json = await response.json();
return json['public_repos'];
}
ArfatSalman, octocat, norvig ๊ณ์ ์ด ํ์ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ์ฐ๋ฆฌ๋ ๋ค์์ ์ํํฉ๋๋ค.
const users = [
'ArfatSalman',
'octocat',
'norvig'
];
const counts = users.map(async username => {
const count = await fetchPublicReposCount(username);
return count;
});
.map ์ฝ๋ฐฑ์ Await์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ์ฌ๊ธฐ์ counts๋ promise์ ๋ฐฐ์ด์ด๊ณ .map์ ์ง์ ๋ ๊ฐ ์ฌ์ฉ์์ ๋ํ ์ต๋ช ์ฝ๋ฐฑ์ ๋๋ค.
Wait๋ฅผ ์ง๋์น๊ฒ ์ผ๊ด๋๊ฒ ์ฌ์ฉํจ
์ด ์ฝ๋๋ฅผ ์๋ก ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
async function fetchAllCounts(users) {
const counts = [];
for (let i = 0; i < users.length; i++) {
const username = users[i];
const count = await fetchPublicReposCount(username);
counts.push(count);
}
return counts;
}
์ฌ๊ธฐ์ repo ๋ฒํธ๋ count ๋ณ์์ ๋ฐฐ์น๋๊ณ ์ด ์ซ์๋ counts ๋ฐฐ์ด์ ์ถ๊ฐ๋ฉ๋๋ค. ์ฝ๋์ ๋ฌธ์ ์ ์ ์ฒซ ๋ฒ์งธ ์ฌ์ฉ์์ ๋ฐ์ดํฐ๊ฐ ์๋ฒ์์ ๋์ฐฉํ ๋๊น์ง ๋ชจ๋ ํ์ ์ฌ์ฉ์๊ฐ ๋๊ธฐ ๋ชจ๋์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ ํ ๋ฒ์ ํ ๋ช ์ ์ฌ์ฉ์๋ง ์ฒ๋ฆฌ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด ํ ๋ช ์ ์ฌ์ฉ์๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ฝ 300ms๊ฐ ๊ฑธ๋ฆฐ๋ค๋ฉด ๋ชจ๋ ์ฌ์ฉ์์ ๊ฒฝ์ฐ ์ด๋ฏธ XNUMX์ด์ ๋๋ค. ์์ ์๊ฐ์ ์ ํ์ ์ผ๋ก ์ฌ์ฉ์ ์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ๊ทธ๋ฌ๋ Repo ์๋ฅผ ์ป๋ ๊ฒ์ ์๋ก ์์กดํ์ง ์์ผ๋ฏ๋ก ํ๋ก์ธ์ค๋ฅผ ๋ณ๋ ฌํํ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด์๋ .map ๋ฐ Promise.all ์์ ์ด ํ์ํฉ๋๋ค.
async function fetchAllCounts(users) {
const promises = users.map(async username => {
const count = await fetchPublicReposCount(username);
return count;
});
return Promise.all(promises);
}
Promise.all์ ์ฝ์์ ๋ฐฐ์ด์ ์ ๋ ฅ์ผ๋ก ๋ฐ๊ณ ์ฝ์์ ๋ฐํํฉ๋๋ค. ํ์๋ ๋ฐฐ์ด์ ๋ชจ๋ Promise๊ฐ ์๋ฃ๋ ํ ๋๋ ์ฒซ ๋ฒ์งธ ๊ฑฐ๋ถ ์ ์๋ฃ๋ฉ๋๋ค. ๋ชจ๋ ๋์์ ์์๋์ง ์๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๋์ ์์์ ๋ณด์ฅํ๋ ค๋ฉด p-map์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ฒฐ๋ก
๋น๋๊ธฐ ๊ธฐ๋ฅ์ ๊ฐ๋ฐ์ ์ ์ ๋ ์ค์ํด์ง๊ณ ์์ต๋๋ค. ์, ๋น๋๊ธฐ ๊ธฐ๋ฅ์ ์ ์์ ์ผ๋ก ์ฌ์ฉํ๋ ค๋ฉด ๋ค์์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
Skillbox๋ ๋ค์์ ๊ถ์ฅํฉ๋๋ค.
- ์ค๊ธฐ ์ฝ์ค
"๋ชจ๋ฐ์ผ ๊ฐ๋ฐ์ PRO" .- ์จ๋ผ์ธ ๊ฐ์ข ์ ์ฉ
"Python์ ๋ฐ์ดํฐ ๋ถ์๊ฐ" .- XNUMX๋ ์ค์ต ์ฝ์ค
"์ ๋ PRO ์น ๊ฐ๋ฐ์์ ๋๋ค" .
์ถ์ฒ : habr.com