์ฝ”์–ดJS ์ •๋ฆฌ ๐Ÿ“–| ์ฝœ๋ฐฑ ์ง€์˜ฅ๊ณผ ๋น„๋™๊ธฐ ์ œ์–ด

hyebin Joยท2022๋…„ 4์›” 9์ผ
0

์ฝœ๋ฐฑ์ง€์˜ฅ(callback hell)

์ฝœ๋ฐฑ์ง€์˜ฅ(callback hell)์ด๋ž€, ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์ต๋ช…ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์ด ๋ฐ˜๋ณต๋˜์–ด ์ฝ”๋“œ์˜ ๋“ค์—ฌ์“ฐ๊ธฐ ์ˆ˜์ค€์ด ๊ฐ๋‹นํ•˜๊ธฐ ํž˜๋“ค ์ •๋„๋กœ ๊นŠ์–ด์ง€๋Š” ํ˜„์ƒ์ž…๋‹ˆ๋‹ค.
์ฆ‰, ์ฝœ๋ฐฑํ•จ์ˆ˜์— ๋˜ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ณ , ๊ทธ ์ฝœ๋ฐฑํ•จ์ˆ˜์— ๋˜ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์ด ๋ฐ˜๋ณต๋œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.
์ฃผ๋กœ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋Ÿฐ ํ˜•ํƒœ๊ฐ€ ์ž์ฃผ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

Promise

Promise๋Š” ๋น„๋™๊ธฐ์ ์ธ ๊ฒƒ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์ฝœ๋ฐฑํ•จ์ˆ˜ ๋Œ€์‹ ์— ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์ผ ์ˆ˜ ์žˆ๋Š” ์˜ค๋ธŒ์ ํŠธ์ž…๋‹ˆ๋‹ค.

const promise = new Promise((resolve, reject) => {
  console.log('doing something...');
  setTimeout(() => 
    resolve('์„ฑ๊ณต')
    //reject('์‹คํŒจ')
  , 200);
})
//Promise๋ฅผ ๋งŒ๋“œ๋Š” ์ˆœ๊ฐ„ ์ „๋‹ฌํ•œ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ์ฆ‰์‹œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
//์ด ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š” resolve, reject๋ผ๋Š” ์ฝœ๋ฐฑ์„ ์ „๋‹ฌ๋ฐ›์Šต๋‹ˆ๋‹ค.
//๋น„๋™๊ธฐ์ž‘์—…์ด ์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ resolve(...)๋ฅผ, ์‹คํŒจํ•œ ๊ฒฝ์šฐ reject(...) ํ˜ธ์ถœ

promise
  .then(console.log) //resolve()๊ฐ€ ๋ฐ˜ํ™˜๋œ ๊ฒฝ์šฐ ์‹คํ–‰
  .catch(console.log) //reject()๊ฐ€ ๋ฐ˜ํ™˜๋œ ๊ฒฝ์šฐ ์‹คํ–‰
  .finally(console.log('finally'));
//finally() ๋ฉ”์†Œ๋“œ๋Š” Promise๊ฐ€ resolve ํ˜น์€ reject๊ฐ€ ๋ฐ˜ํ™˜๋˜์—ˆ๋Š”์ง€์— ๊ด€๊ณ„์—†์ด ์ง€์ •๋œ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์–ด๋– ํ•œ ์ธ์ˆ˜๋„ ์ „๋‹ฌ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋น„๋™๊ธฐ ์ž‘์—…์˜ ๋™๊ธฐ์  ํ‘œํ˜„(1) - Promise

new Promise(resolve => 
  setTimeout(() => {
    const name = '์—์Šคํ”„๋ ˆ์†Œ';
    console.log(name);
    resolve(name);
  }, 500)
).then(prevName => new Promise(resolve => 
  setTimeout(() => {
    const name = prevName + ', ์•„๋ฉ”๋ฆฌ์นด๋…ธ';
    console.log(name);
    resolve(name);
  }, 500))
).then(prevName => new Promise(resolve => 
  setTimeout(() => {
    const name = prevName + ', ์นดํŽ˜๋ชจ์นด';
    console.log(name);
    resolve(name);
  }, 500))
).then(prevName => new Promise(resolve => 
  setTimeout(() => {
    const name = prevName + ', ์นดํŽ˜๋ผ๋–ผ';
    console.log(name);
  }, 500))
);

//์—์Šคํ”„๋ ˆ์†Œ
//์—์Šคํ”„๋ ˆ์†Œ, ์•„๋ฉ”๋ฆฌ์นด๋…ธ
//์—์Šคํ”„๋ ˆ์†Œ, ์•„๋ฉ”๋ฆฌ์นด๋…ธ, ์นดํŽ˜๋ชจ์นด
//์—์Šคํ”„๋ ˆ์†Œ, ์•„๋ฉ”๋ฆฌ์นด๋…ธ, ์นดํŽ˜๋ชจ์นด, ์นดํŽ˜๋ผ๋–ผ
//(0.5์ดˆ๋งˆ๋‹ค ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ)

์œ„์˜ ๋น„๋™๊ธฐ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ช…ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด, ์‹คํ–‰์‹œ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const addEspresso = ()=> new Promise(resolve => {
  setTimeout(() => {
    const name = '์—์Šคํ”„๋ ˆ์†Œ'
    console.log(name);
    resolve(name);
  }, 500)
});
const addAmericano = (prevName) => new Promise(resolve => {
  setTimeout(() => {
    const name = prevName + ', ์•„๋ฉ”๋ฆฌ์นด๋…ธ';
    console.log(name);
    resolve(name);
  }, 500)
});
const addCafeMocha = (prevName) => new Promise(resolve => {
  setTimeout(() => {
    const name = prevName + ', ์นดํŽ˜๋ชจ์นด';
    console.log(name);
    resolve(name);
  }, 500)
});
const addCafeLatte = (prevName) => new Promise(resolve => {
  setTimeout(() => {
    const name = prevName + ', ์นดํŽ˜๋ผ๋–ผ';
    console.log(name);
    resolve(name);
  }, 500)
});

addEspresso()
.then(prevName => addAmericano(prevName))
.then(prevName => addCafeMocha(prevName))
.then(prevName => addCafeLatte(prevName));

//์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ๋ฐ›์•„์˜ค๋Š” ๊ฐ’์œผ๋กœ ๋ฐ”๋กœ ๋‹ค์Œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

addEspresso()
.then(addAmericano)
.then(addCafeMocha)
.then(addCafeLatte);

๋ฐ˜๋ณต์ ์ธ ํ•จ์ˆ˜ ์„ ์–ธ์„ ์งง๊ฒŒ ํ‘œํ˜„ํ•˜๋ฉด,

const addCoffee = function(name) {
  return function(prevName) {
    return new Promise(resolve => {
      setTimeout(() => {
        var newName = prevName ? (prevName + ', ' + name) : name;
        console.log(newName);
        resolve(newName);
      }, 500);
    });
  };
};

addCoffee('์—์Šคํ”„๋ ˆ์†Œ')()
.then(addCoffee('์•„๋ฉ”๋ฆฌ์นด๋…ธ'))
.then(addCoffee('์นดํŽ˜๋ชจ์นด'))
.then(addCoffee('์นดํŽ˜๋ผ๋–ผ'));

Generator

function ๋’ค์— *๊ฐ€ ๋ถ™์€ ํ•จ์ˆ˜๋Š” generatorํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค. generator ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋ฉด Iterator๊ฐ€ ๋ฐ˜ํ™˜๋˜๋Š”๋ฐ, ์ด Iterator๋Š” next๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
next ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด generatorํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๊ฐ€์žฅ ๋จผ์ € ๋“ฑ์žฅํ•˜๋Š” yield์—์„œ ์‹คํ–‰์„ ๋ฉˆ์ถ”๊ณ , ์ดํ›„ ๋‹ค์‹œ next๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ ํ•˜๋ฉด ์•ž์„œ ๋ฉˆ์ท„๋˜ ๋ถ€๋ถ„์—์„œ ์‹œ์ž‘ํ•ด์„œ ๊ทธ ๋‹ค์Œ์— ๋“ฑ์žฅํ•˜๋Š” yield์—์„œ ์‹คํ–‰์„ ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋Š” ์‹œ์ ๋งˆ๋‹ค next๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์ค€๋‹ค๋ฉด generatorํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์†Œ์Šค๊ฐ€ ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ์ˆœ์ฐจ์ ์œผ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.
๋น„๋™๊ธฐ ์ž‘์—…์˜ ๋™๊ธฐ์  ํ‘œํ˜„(2) - Generator

const addCoffee = function (prevName, name) {
  setTimeout(function() {
    coffeeMaker.next(prevName ? prevName + ', ' + name : name);
  }, 500);
};

const coffeeGenerator = function* () {
  const espresso = yield addCoffee('', '์—์Šคํ”„๋ ˆ์†Œ');
  console.log(espresso);
  const americano = yield addCoffee(espresso, '์•„๋ฉ”๋ฆฌ์นด๋…ธ');
  console.log(americano);
  const mocha = yield addCoffee(americano, '์นดํŽ˜๋ชจ์นด');
  console.log(mocha);
  const latte = yield addCoffee(mocha, '์นดํŽ˜๋ผ๋–ผ');
  console.log(latte);
};

const coffeeMaker = coffeeGenerator();
coffeeMaker.next();

//0.5์ดˆ๋งˆ๋‹ค next๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ

async / await

๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ ์ž ํ•˜๋Š” ํ•จ์ˆ˜ ์•ž์— async๋ฅผ ๋ถ™์ด๊ณ , await์€ async๊ฐ€ ๋ถ™์€ ํ•จ์ˆ˜ ์•ˆ์—์„œ๋งŒ ์“ธ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์งˆ์ ์ธ ๋น„๋™๊ธฐ ์ž‘์—…์ด ํ•„์š”ํ•œ ์œ„์น˜๋งˆ๋‹ค await๋ฅผ ํ‘œ๊ธฐํ•˜๋ฉด ๋’ค์˜ ๋‚ด์šฉ์„ ์ž๋™์œผ๋กœ Promise๋กœ ์ „ํ™˜ํ•˜๊ณ , ํ•ด๋‹น ๋‚ด์šฉ์ด resolve๋œ ์ดํ›„์—์•ผ ๋‹ค์Œ์œผ๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

function fetchData() {
  return new Promise((resolve, reject) => {
    //do network request.....
    resolve('์„ฑ๊ณต');
  });
}

async function fetchData2() {
  //do network request...
  return '์„ฑ๊ณต';
}

fetchData().then(console.log); //์„ฑ๊ณต
fetchData2().then(console.log); //์„ฑ๊ณต

๋น„๋™๊ธฐ ์ž‘์—…์˜ ๋™๊ธฐ์  ํ‘œํ˜„(3) - Promise + Async/await

const addCoffee = name =>
  new Promise(resolve =>
    setTimeout(() => resolve(name), 500)
  );

const coffeeMaker = async() => {
  let coffeeList = '';
  const _addCoffee = async name => {
    coffeeList += (coffeeList ? ',' : '') + await addCoffee(name);
  };
  await _addCoffee('์—์Šคํ”„๋ ˆ์†Œ');
  console.log(coffeeList);
  await _addCoffee('์•„๋ฉ”๋ฆฌ์นด๋…ธ');
  console.log(coffeeList);
  await _addCoffee('์นดํŽ˜๋ชจ์นด');
  console.log(coffeeList);
  await _addCoffee('์นดํŽ˜๋ผ๋–ผ');              
  console.log(coffeeList);
};
coffeeMaker();

0๊ฐœ์˜ ๋Œ“๊ธ€