์˜ˆ์ œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JavaScript์˜ Async/Await๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด ๊ธฐ์‚ฌ์˜ ์ €์ž๋Š” 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์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

๋น„๋™๊ธฐ ๊ธฐ๋Šฅ์€ ๊ฐœ๋ฐœ์— ์ ์  ๋” ์ค‘์š”ํ•ด์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์Œ, ๋น„๋™๊ธฐ ๊ธฐ๋Šฅ์„ ์ ์‘์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ ๋ฐ˜๋ณต์ž. JavaScript ๊ฐœ๋ฐœ์ž๋Š” ์ด์— ๋Œ€ํ•ด ์ž˜ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Skillbox๋Š” ๋‹ค์Œ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€