Async / Await

Async / Await

Front-end developer WONISM
Interested in ReactJS, RxJS and ReasonML.

ES2017(ECMA-262)μ—μ„œ μƒˆλ‘­κ²Œ μΆ”κ°€λœ async/awaitλŠ” 비동기 ν•¨μˆ˜λ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ ν‚€μ›Œλ“œμ΄λ‹€.
처음 μ œμ•ˆλœ 것은 TypeScript 1.7μ˜€λ‹€.
λ˜ν•œ, async/awaitλŠ” Promiseμœ„μ— κ΅¬μΆ•λ˜μ—ˆκ³ , 기쑴의 λͺ¨λ“  ν”„λ‘œλ―ΈμŠ€ 기반 API와 ν˜Έν™˜λ˜κΈ° λ•Œλ¬Έμ— ν”„λ‘œλ―ΈμŠ€μ™€ 같이 μ‚¬μš©ν•˜κ±°λ‚˜, ν”„λ‘œλ―ΈμŠ€λ₯Ό λŒ€μ²΄ν•  수 μžˆλ‹€.
비동기 λ™μž‘μ„ μœ„ν•œ 동기식 ꡬ문을 μ œκ³΅ν•¨μœΌλ‘œμ¨ μ½”λ“œ 가독성을 높일 수 있으며, μ—λŸ¬ 핸듀링을 μœ„ν•΄ try/catchλ₯Ό μ‚¬μš©ν•œλ‹€.

μ‹œμž‘ν•˜κΈ° 전에

async와 awaitλŠ” ν‚€μ›Œλ“œμ΄λ―€λ‘œ polyfill이 μ—†μœΌλ©°, 이전 λΈŒλΌμš°μ €λ₯Ό μ§€μ›ν•˜λ €λ©΄, babel λ“± 트랜슀파일러λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
μ‚¬μš©ν•˜λŠ” λΈŒλΌμš°μ €κ°€ async, awaitλ₯Ό μ§€μ›ν•˜λŠ”μ§€ ν™•μΈν•˜λ €λ©΄, Can I use?μ—μ„œ ν•΄λ‹Ή ν‚€μ›Œλ“œλ₯Ό κ²€μƒ‰ν•˜λ©΄ λœλ‹€.

예제 μ½”λ“œλ₯Ό 톡해 async/await μ‚΄νŽ΄λ³΄κΈ°

function willBeAwaited() {
  return new Promise(function (resolve) {
    setTimeout(resolve, 400, 42);
  });
}

async function asyncFunc () {
  const resolvedValue = await willBeAwaited();
  console.log(resolvedValue);

  return resolvedValue + 500;
}

asyncFunc()
  .then(function (resolvedValue) {
    console.log(resolvedValue);
  });

// 42
// 542

asyncν‚€μ›Œλ“œλŠ” 일반적인 ν•¨μˆ˜λ₯Ό μžλ™μœΌλ‘œ ν”„λ‘œλ―ΈμŠ€ ν˜•νƒœλ‘œ λ§Œλ“€λ©°, asyncν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ ν•΄λ‹Ή ν•¨μˆ˜κ°€ 무엇을 λ°˜ν™˜ν•˜λ“  resolveλœλ‹€. λ˜ν•œ, async ν•¨μˆ˜λŠ” await의 μ‚¬μš©μ„ κ°€λŠ₯ν•˜κ²Œ ν•œλ‹€.
awaitν‚€μ›Œλ“œλŠ” ν”„λ‘œλ―ΈμŠ€ 객체와 μž‘λ™ν•˜λ©°, ν•¨μˆ˜μ˜ 호좜 μ•žμ— μ‚¬μš©λ˜λ©΄ ν”„λ‘œλ―ΈμŠ€κ°€ 해결될 λ•ŒκΉŒμ§€ μ½”λ“œ 싀행을 μ€‘λ‹¨ν•˜κ²Œ ν•œλ‹€. awaitλŠ” 였직 asyncν•¨μˆ˜μ™€ μ‚¬μš©λ  수 μžˆλ‹€.

asyncFuncλ₯Ό 일반 ν”„λ‘œλ―ΈμŠ€ μŠ€νƒ€μΌλ‘œ μž¬μž‘μ„±ν•˜λ©΄, λ‹€μŒκ³Ό κ°™λ‹€.

function asyncFunc() {
  return willBeAwaited()
    .then((resolvedValue) => {
      console.log(resolvedValue);

      return resolvedValue + 500;
    });
}

μ—λŸ¬ 핸듀링

ν”„λ‘œλ―ΈμŠ€λŠ” ν•΄κ²°(resolve)될 μˆ˜λ„ 있고, 거절(reject)될 수 있으며, κ±°μ ˆλœλ‹€λ©΄ ν”„λ‘œλ―ΈμŠ€ 객체의 Promise.prototype.catchλ©”μ†Œλ“œλ₯Ό 톡해 μ²˜λ¦¬ν•œλ‹€.
async/await의 κ²½μš°μ—λŠ” try { ... } catch { ... }λ₯Ό μ‚¬μš©ν•œλ‹€.

function willBeAwaited() {
  return new Promise(function (resolve, reject) {
    setTimeout(reject, 400, 'Error occured!');
  });
}

async function asyncFunc () {
  try {
    const resolvedValue = await willBeAwaited();
    console.log(resolvedValue);

    return resolvedValue + 500;
  } catch (e) {
    console.log(e);

    return 'Error occured when \'willBeAwaited\' is executed';
  }
}

asyncFunc()
  .then(function (resolvedValue) {
    console.log(resolvedValue);
  });

// Error occured!
// Error occured when 'willBeAwaited' is executed

λ§Œμ•½, async ν•¨μˆ˜μ—μ„œ 거절된 ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜λ €λ©΄ throwλ₯Ό 톡해 μ—λŸ¬λ₯Ό λ˜μ§€λ©΄ λœλ‹€.

function willBeAwaited() {
  return new Promise(function (resolve, reject) {
    setTimeout(reject, 400, 'Error occured!');
  });
}

async function asyncFunc () {
  try {
    const resolvedValue = await willBeAwaited();
    console.log(resolvedValue);

    return resolvedValue + 500;
  } catch (e) {
    console.log(e);

    throw new Error(e);
  }
}

asyncFunc()
  .then(function (resolvedValue) {
    console.log(resolvedValue);
  })
  .catch(function (e) {
    console.log(e);
  });

// Error occured!
// Error occured!

async/await의 ν•œκ³„

1. asyncκ°€ μ—†μ΄λŠ” awaitλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

μ „μ—­ μŠ€μ½”ν”„λ‚˜ 일반 ν•¨μˆ˜ μŠ€μ½”ν”„ μ•ˆμ—μ„œ awaitλ₯Ό 직접 μ‚¬μš©ν•  수 μ—†μŒμ„ μ˜λ―Έν•œλ‹€.

async function one() {
  return 1;
}

// const num = await one();
// can not be executed

async function main() {
  const num = await one();
  console.log(num);
}

main();

2. Promise.allκ³Ό 같은 경우λ₯Ό λŒ€μ²΄ν•  수 μ—†λ‹€.

λͺ¨λ“  비동기 호좜이 끝날 λ•ŒκΉŒμ§€ κΈ°λ‹€λ €μ•Ό ν•˜λŠ” 경우, Promise.all을 μ‚¬μš©ν•˜λŠ” 것이 훨씬 μ’‹λ‹€.

function sleep(ms = 0) {
  return new Promise(resolve => setTimeout(function () {
    resolve(ms);
  }, ms));
}

(async function awaitAyncFunctions() {
  const start = Date.now();

  await sleep(1000);
  await sleep(3000);
  await sleep(2000);

  const end = Date.now();

  console.log(`execution time is ${Math.round((end - start) / 1000)}seconds.`);
  // execution time is 6seconds.
})();

(async function awaitAyncFunctions() {
  const start = Date.now();

  const results = await
  Promise.all([sleep(1000), sleep(3000), sleep(2000)]);

  const end = Date.now();

  console.log(`execution time is ${Math.round((end - start) / 1000)}seconds.`);
  // execution time is 3seconds.
})();

μ°Έκ³