λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
javascript/πŸ“– study

[11μ£Όμ°¨ μŠ€ν„°λ””]46μž₯-μ œλ„ˆλ ˆμ΄ν„°μ™€ async / await

by HomieKim 2022. 4. 8.

μ œλ„ˆλ ˆμ΄ν„°μ™€ async/await

μ œλ„ˆλ ˆμ΄ν„°λž€?

  • ES6μ—μ„œ λ„μž… 된 μ œλ„ˆλ ˆμ΄ν„°λŠ” μ½”λ“œ λΈ”λ‘μ˜ 싀행을 μΌμ‹œ 쀑지 ν–ˆλ‹€κ°€ ν•„μš”ν•œ μ‹œμ μ— μž¬κ°œν•  수 μžˆλŠ” νŠΉμˆ˜ν•œ ν•¨μˆ˜ μž…λ‹ˆλ‹€.
  • 일반 ν•¨μˆ˜μ™€μ˜ 차이
  1. μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” ν•¨μˆ˜ ν˜ΈμΆœμžμ—κ²Œ ν•¨μˆ˜ μ‹€ν–‰μ˜ μ œμ–΄κΆŒμ„ 양도할 수 μžˆλ‹€.

    • μ΄λ•Œ ν•¨μˆ˜μ˜ μ œμ–΄κΆŒμ„ ν˜ΈμΆœμžμ—κ²Œ λ„˜κΈ°λŠ” 것을 양도(yield)라고 함
  2. μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” ν•¨μˆ˜ ν˜ΈμΆœμžμ™€ ν•¨μˆ˜μ˜ μƒνƒœλ₯Ό μ£Όκ³  받을 수 μžˆλ‹€.

    • μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” ν•¨μˆ˜ ν˜ΈμΆœμžμ—κ²Œ μƒνƒœλ₯Ό 전달할 수 있고 ν•¨μˆ˜ 호좜자둜 λΆ€ν„° μƒνƒœλ₯Ό 전달 받을 μˆ˜λ„ μžˆλ‹€.
  3. μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ μ œλ„ˆλ ˆμ΄ν„° 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.

    • μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ ν•¨μˆ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” 것이 μ•„λ‹ˆλΌ μ΄ν„°λŸ¬λΈ”μ΄λ©΄μ„œ λ™μ‹œμ— μ΄ν„°λ ˆμ΄ν„°μΈ μ œλ„ˆλ ˆμ΄ν„° 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.

μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜μ˜ μ •μ˜

  • μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” function* ν‚€μ›Œλ“œλ‘œ μ •μ˜
  • ν•˜λ‚˜ μ΄μƒμ˜ yield ν‘œν˜„μ‹μ„ ν¬ν•¨ν•œλ‹€.
  • μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ μ •μ˜ν•  수 μ—†λ‹€.
  • μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ‘œ ν˜ΈμΆœν•  수 μ—†λ‹€.
// μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜ μ„ μ–Έλ¬Έ
function* genDecFunc() {
  yield 1;
}

// μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜ ν‘œν˜„μ‹
const genExpFunc = function* () {
  yield 1;
};

// μ œλ„ˆλ ˆμ΄ν„° λ©”μ„œλ“œ
const obj = {
  * genObjMethod() {
    yield 1;
  }
};

// μ œλ„ˆλ ˆμ΄ν„° 클래슀 λ©”μ„œλ“œ
class MyClass {
  * genClsMethod() {
    yield 1;
  }
}

μ œλ„ˆλ ˆμ΄ν„° 객체

  • μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ 일반 ν•¨μˆ˜μ²˜λŸΌ ν•¨μˆ˜ μ½”λ“œ 블둝을 μ‹€ν–‰ν•˜λŠ” 것이 μ•„λ‹ˆλΌ μ œλ„ˆλ ˆμ΄ν„° 객체λ₯Ό 생성해 λ°˜ν™˜
  • μ œλ„ˆλ ˆμ΄ν„° κ°μ²΄λŠ” μ΄ν„°λŸ¬λΈ” μ΄λ©΄μ„œ λ™μ‹œμ— μ΄ν„°λ ˆμ΄ν„°
  • μ΄ν„°λ ˆμ΄ν„° μ΄λ―€λ‘œ next() λ©”μ„œλ“œλ₯Ό 가짐
  • λ‹€λ₯Έ μ΄ν„°λ ˆμ΄ν„°μ™€ λ‹€λ₯΄κ²Œ return, throw λ©”μ„œλ“œλ₯Ό 가진닀.
  • λ©”μ„œλ“œ λ™μž‘ 방식
    • next : yield ν‘œν˜„μ‹ κΉŒμ§€ μ½”λ“œ 블둝을 μ‹€ν–‰ν•˜κ³  yield 된 값을 value ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ, false 값을 κ°–λŠ” doneν”„λ‘œνΌν‹°λ₯Ό 가진 리절트 객체λ₯Ό λ°˜ν™˜
    • return : 인수둜 전달 받은 값을 value ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ, done ν”„λ‘œνΌν‹° 값이 true 인 리절트 객체 λ°˜ν™˜
    • throw : 인수둜 전달 받은 μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€κ³  undefined 값을 value ν”„λ‘œνΌν‹°μ˜ κ°’μœΌλ‘œ, done ν”„λ‘œνΌν‹°μ˜ 값이 true인 리절트 객체 λ°˜ν™˜
function* genFunc() {
  try {
    yield 1;
    yield 2;
    yield 3;
  } catch (e) {
    console.error(e);
  }
}

const generator = genFunc();

console.log(generator.next()); // {value: 1, done: false}
// return ν–ˆμ„ λ•Œ
console.log(geneator.return('End!')); // {value: "End!", done: true}
// throw ν–ˆμ„ λ•Œ
console.log(generator.throw('Error!')); // {value: undefined, done: true}

μ œλ„ˆλ ˆμ΄ν„°μ˜ μΌμ‹œ 쀑지와 재개

  • μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜λŠ” μΌλ°˜ν•¨μˆ˜μ²˜λŸΌ μ½”λ“œ 블둝을 일괄 μ‹€ν–‰ν•˜λŠ” 것이 μ•„λ‹ˆλΌ yield ν‘œν˜„μ‹ κΉŒμ§€λ§Œ μ‹€ν–‰
  • yield ν‚€μ›Œλ“œλŠ” μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜μ˜ 싀행을 μΌμ‹œ 쀑지 μ‹œν‚€κ±°λ‚˜ yield ν‚€μ›Œλ“œ 뒀에 μ˜€λŠ” ν‘œν˜„μ‹μ˜ 평가 κ²°κ³Όλ₯Ό μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜ ν˜ΈμΆœμžμ—κ²Œ λ°˜ν™˜
function* genFunc(){
    yield 1;
    yield 2;
    yield 3;
}

// μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜ μ‹€ν–‰μ‹œ μ œλ„ˆλ ˆμ΄ν„° 객체λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
const generator = genFunc();
// next λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ yield ν‘œν˜„μ‹ κΉŒμ§€ μ‹€ν–‰ 되고 μΌμ‹œμ€‘μ§€λ©λ‹ˆλ‹€.
// μ΄λ•Œ ν•¨μˆ˜μ˜ μ œμ–΄κΆŒμ΄ 호좜자둜 양도(yield) λ©λ‹ˆλ‹€.
console.log(generator.next()); // { value: 1, done : false}
console.log(generator.next()); // { value: 2, done : false}
console.log(generator.next()); // { value: 3, done : false}
// yield ν‘œν˜„μ‹μ΄ λͺ¨λ‘ μ‹€ν–‰ λ˜μ—ˆμœΌλ―€λ‘œ ν•¨μˆ˜ λ§ˆμ§€λ§‰ κΉŒμ§€ μ‹€ν–‰ λ©λ‹ˆλ‹€.
// λ°˜ν™˜λ˜λŠ” value 값은 undefined, done ν”„λ‘œνΌν‹°λŠ” true κ°€ λ©λ‹ˆλ‹€. 
console.log(generator.next()); // { value: undefined, done : true}
  • μ΄ν„°λ ˆμ΄ν„°μ˜ next λ©”μ„œλ“œμ™€ 달리 μ œλ„ˆλ ˆμ΄ν„° 객체의 next λ©”μ„œλ“œ μ—λŠ” 인수λ₯Ό 전달할 수 μžˆλ‹€.
  • μ œλ„ˆλ ˆμ΄ν„° 객체의 next λ©”μ„œλ“œμ— μ „λ‹¬ν•œ μΈμˆ˜λŠ” μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜μ˜ yield ν‘œν˜„μ‹μ„ ν• λ‹Ήλ°›λŠ” λ³€μˆ˜μ— ν• λ‹Ή λœλ‹€.

μ œλ„ˆλ ˆμ΄ν„°μ˜ ν™œμš©

  • λ¬΄ν•œ μ΄ν„°λŸ¬λΈ”μ„ μƒμ„±ν•˜λŠ” μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜
// λ¬΄ν•œ μ΄ν„°λŸ¬λΈ”μ„ μƒμ„±ν•˜λŠ” μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜
const infiniteFibonacci = (function* () {
  let [pre, cur] = [0, 1];

  while (true) {
    [pre, cur] = [cur, pre + cur];
    yield cur;
  }
}());

// infiniteFibonacciλŠ” λ¬΄ν•œ μ΄ν„°λŸ¬λΈ”μ΄λ‹€.
for (const num of infiniteFibonacci) {
  if (num > 10000) break;
  console.log(num); // 1 2 3 5 8...2584 4181 6765
}
  • 비동기 처리
const fetch = require('node-fetch'); // nodeν™˜κ²½μ—μ„œ fetch ν•¨μˆ˜ μ‚¬μš©ν•˜κΈ° μœ„ν•œ 라이브러리

// μ œλ„ˆλ ˆμ΄ν„° μ‹€ν–‰κΈ°
const async = generatroFunc => {
    const generator = generatorFunc();

    const onResolved = arg => {
        const rst = generator.next(arg);

        return rst.done ? rst.value : rst.value.then(res => onResolved(res));
    };

    return onResolved; 
};

(async(function* fetchTodo(){
    const url = 'http://jsonplaceholder.typicode.com/todos/1';

    const response = yield fetch(url);
    const todo = yield response.json();
    consoloe.log(todo);
})());

async / await

  • μ œλ„ˆλ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•΄μ„œ 비동기 처리λ₯Ό κ΅¬ν˜„ν•˜λ©΄ μ½”λ“œκ°€ 맀우 λ³΅μž‘ν•΄μ§
  • μ œλ„ˆλ ˆμ΄ν„° 보닀 비동기 처리λ₯Ό κ°„λ‹¨ν•˜κ²Œ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ async /await λ„μž…
  • ν”„λ‘œλ―ΈμŠ€λ₯Ό 기반으둜 λ™μž‘
const fetch = require('node-fetch');

async function fetchTodo() {
    const url = 'https://jsonplaceholder.typicode.com/todos/1';

    const response = await fetch(url);
    const todo = await response.json();
    console.log(todo);
};

async ν•¨μˆ˜

  • await ν‚€μ›Œλ“œλŠ” λ°˜λ“œμ‹œ async ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
  • async ν•¨μˆ˜λŠ” λͺ…μ‹œμ μœΌλ‘œ ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜μ§€ μ•Šλ”λΌλ„ μ•”λ¬΅μ μœΌλ‘œ λ°˜ν™˜κ°’μ„ resolveν•˜λŠ” ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜
  • 클래슀의 constructor λ©”μ„œλ“œλŠ” λ°˜λ“œμ‹œ 값을 λ°˜ν™˜ν•΄μ•Ό ν•˜λ―€λ‘œ async ν•¨μˆ˜κ°€ 될 수 μ—†μŠ΅λ‹ˆλ‹€.

await ν‚€μ›Œλ“œ

  • await ν‚€μ›Œλ“œλŠ” settled μƒνƒœ(비동기 μ²˜λ¦¬κ°€ μˆ˜ν–‰λœ μƒνƒœ)κ°€ 될 λ•ŒκΉŒμ§€ λŒ€κΈ°ν•˜λ‹€κ°€ settled μƒνƒœκ°€ 되면 ν”„λ‘œλ―ΈμŠ€κ°€ resolveν•œ 처리결과λ₯Ό λ°˜ν™˜
  • await ν‚€μ›Œλ“œλŠ” λ°˜λ“œμ‹œ ν”„λ‘œλ―ΈμŠ€ μ•žμ—μ„œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
  • 즉, λ‹€μŒ 싀행을 μΌμ‹œ μ€‘μ§€μ‹œμΌ°λ‹€κ°€ ν”„λ‘œλ―ΈμŠ€κ°€ settled μƒνƒœκ°€ 되면 λ‹€μ‹œ μž¬κ°œν•˜λŠ” 것

μ—λŸ¬ 처리

  • 비동기 처리λ₯Ό μœ„ν•œ 콜백 νŒ¨ν„΄μ€ try...catch문을 μ‚¬μš©ν•΄ μ—λŸ¬λ₯Ό 캐치 ν•  수 μ—†λ‹€.
  • async / await μ—μ„œλŠ” try...catch 둜 μ—λŸ¬ 처리 κ°€λŠ₯

    μ—λŸ¬λŠ” 호좜자 λ°©ν–₯으둜 μ „νŒŒ λ˜λŠ”λ° 비동기 ν•¨μˆ˜μ˜ ν˜ΈμΆœμžκ°€ ν•΄λ‹Ή 비동기 ν•¨μˆ˜κ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ—

  • λ¬Όλ‘  async / await은 ν”„λ‘œλ―ΈμŠ€λ‘œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— catch 후속 처리 λ©”μ„œλ“œλ‘œλ„ μ—λŸ¬ 처리 κ°€λŠ₯

λŒ“κΈ€