๐Ÿ“ŒLanguage/JavaScript

[Deep Dive] ํ”„๋กœ๋ฏธ์Šค, Promise, Promise.all

hellohailie 2023. 1. 3. 08:06

โœ”๏ธ ์ด๋ฒˆ ์ •๋…์„ ํ†ตํ•ด ์•Œ๊ฒŒ ๋œ ๊ฒƒ
Promise๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?
Promise.all์€ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

 

<๋‹ต ๋ฏธ๋ฆฌ๋ณด๊ธฐ>

๐Ÿค” Promise๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?

๐Ÿค“ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํŒจํ„ด์œผ๋กœ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์ฝœ๋ฐฑ ํ—ฌ๋กœ ๊ฐ€๋…์„ฑ์ด ๋‚˜์˜๊ณ  ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ค‘ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ์˜ ์ฒ˜๋ฆฌ๊ฐ€ ๊ณค๋ž€ํ•˜๋‹ค๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด ES6์—์„œ ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ๋„์ž…๋˜์–ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ณ  ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์‹œ์ ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๐Ÿค” Promise.all์€ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

๐Ÿค“ ์•ž์„  ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์Œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋•Œ Promise.all ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํŒจํ„ด์œผ๋กœ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์ฝœ๋ฐฑ ํ—ฌ๋กœ ๊ฐ€๋…์„ฑ์ด ๋‚˜์˜๊ณ  ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ค‘ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ์˜ ์ฒ˜๋ฆฌ๊ฐ€ ๊ณค๋ž€ํ•˜๊ณ , ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ๋„ ํ•œ๊ณ„๊ฐ€ ์žˆ๋‹ค. 

 

ES6์—์„œ ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ๋„์ž…๋˜์–ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ณ  ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์‹œ์ ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. 

 


โœ”๏ธ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์™€ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์˜ ํŠน์ง•

๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ž€ ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•œ ํ•จ์ˆ˜๋ฅผ ๋งํ•œ๋‹ค. 

 

๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜๋‹ค ํ•ด๋„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ์ฆ‰์‹œ ์ข…๋ฃŒ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ์—์„œ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์™ธ๋ถ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๋ฉด ๊ธฐ๋Œ€ํ•œ ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค. 

(๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋Š” ํƒœ์Šคํฌ ํ์— ์ €์žฅ๋˜์–ด ๋Œ€๊ธฐํ•˜๋‹ค๊ฐ€, ์ฝœ์Šคํƒ์ด ๋น„๋ฉด ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์˜ํ•ด ์ฝœ ์Šคํƒ์œผ๋กœ ํ‘ธ์‹œ๋˜์–ด ์‹คํ–‰๋œ๋‹ค. )

 


 

โœ”๏ธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ฝœ๋ฐฑ ํŒจํ„ด์˜ ๋‹จ์ 

1. ์ฝœ๋ฐฑํ—ฌ

๋น„๋™๊ธฐ ํ•จ์ˆ˜๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์™ธ๋ถ€์— ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์—†๊ณ , ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ์ˆ˜๋„ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ํ›„์† ์ฒ˜๋ฆฌ๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค. 

โžฅ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ๋ฒ”์šฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋น„๋™๊ธฐ ํ•จ์ˆ˜์— ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ํ›„์† ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค. 

 

๐Ÿ‘‰ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ํ›„์† ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ง€๊ณ  ๋˜๋‹ค์‹œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์ค‘์ฒฉ๋˜์„œ ๋ณต์žก๋„๊ฐ€ ๋†’์•„์ง€๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๋Š”๋ฐ ์ด๋ฅผ ์ฝœ๋ฐฑํ—ฌ(callback hell) ์ด๋ผ๊ณ  ํ•œ๋‹ค. 

 

get('/step1', a => {
  get(`/step2/${a}`, b => {
    get(`/step3/${b}`, c => {
      get(`/step4/${c}`, d => {
        console.log(d);
      });
    });
  });
});

2. ์—๋Ÿฌ ์ฒ˜๋ฆฌ์˜ ํ•œ๊ณ„

try {
  setTimeout(() => { throw new Error('Error!'); }, 1000);
} catch (e) {
  // ์—๋Ÿฌ๋ฅผ ์บ์น˜ํ•˜์ง€ ๋ชปํ•œ๋‹ค
  console.error('์บ์น˜ํ•œ ์—๋Ÿฌ', e);
}

์—๋Ÿฌ๋Š” ํ˜ธ์ถœ์ž ๋ฐฉํ–ฅ์œผ๋กœ ์ „ํŒŒ๋œ๋‹ค. 

ํ•˜์ง€๋งŒ setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒƒ์€ setTimeout ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค. (setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ setTimeout ํ•จ์ˆ˜๋Š” ์ด๋ฏธ ์ฝœ ์Šคํƒ์—์„œ ์ œ๊ฑฐ๋œ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์—!!)

๊ทธ๋ž˜์„œ setTimeout ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋ฐœ์ƒ์‹œํ‚จ ์—๋Ÿฌ๋Š” catch ๋ธ”๋ก์—์„œ ์บ์น˜๋˜์ง€ ์•Š๋Š”๋‹ค. 

 


โœ”๏ธ ํ”„๋กœ๋ฏธ์Šค : ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ƒํƒœ์™€ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด

=> ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ฝœ๋ฐฑ ํŒจํ„ด์˜ ์ฝœ๋ฐฑ ํ—ฌ์ด๋‚˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ๊ณค๋ž€ํ•˜๋‹ค๋Š” ๋ฌธ์ œ๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด ES6์—์„œ ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ๋„์ž…๋˜์—ˆ๋‹ค. 

 

Promise ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ resolve์™€ reject ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ ๋ฐ›๋Š”๋‹ค. 

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์„ฑ๊ณต์‹œ → resolve ํ•จ์ˆ˜ ํ˜ธ์ถœ

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์‹คํŒจ์‹œ → reject ํ•จ์ˆ˜ ํ˜ธ์ถœ

 

  • ํ”„๋กœ๋ฏธ์Šค์˜ ์ƒํƒœ ์ •๋ณด
ํ”„๋กœ๋ฏธ์Šค์˜ ์ƒํƒœ ์ •๋ณด ์˜๋ฏธ ์ƒํƒœ ๋ณ€๊ฒฝ ์กฐ๊ฑด
pending ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์•„์ง ์ˆ˜ํ–‰๋˜์ง€ ์•Š์€ ์ƒํƒœ ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ์ƒ์„ฑ๋œ ์งํ›„ ๊ธฐ๋ณธ ์ƒํƒœ
fulfilled ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰๋œ ์ƒํƒœ(์„ฑ๊ณต) resolve ํ•จ์ˆ˜ ํ˜ธ์ถœ
rejected ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰๋œ ์ƒํƒœ(์‹คํŒจ) reject ํ•จ์ˆ˜ ํ˜ธ์ถœ
// fulfilled๋œ ํ”„๋กœ๋ฏธ์Šค
const fulfilled = new Promise(resolve => resolve(1));

// rejected๋œ ํ”„๋กœ๋ฏธ์Šค
const rejected = new Promise((_, reject) => reject(new Error('error occurred')));

โœ”๏ธ ํ”„๋กœ๋ฏธ์Šค์˜ ํ›„์† ์ฒ˜๋ฆฌ ๋ฉ”์„œ๋“œ

ํ”„๋กœ๋ฏธ์Šค์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ƒํƒœ๊ฐ€ ๋ณ€ํ™”ํ•˜๋ฉด ์ด์— ๋”ฐ๋ฅธ ํ›„์† ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผํ•œ๋‹ค. 

1. Promise.prototype.then

then ๋ฉ”์„œ๋“œ๋Š” ๋‘ ๊ฐœ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(์„ฑ๊ณต ์ฒ˜๋ฆฌ ์ฝœ๋ฐฑ ํ•จ์ˆ˜, ์‹คํŒจ ์ฒ˜๋ฆฌ ์ฝœ๋ฐฑ ํ•จ์ˆ˜)๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›๋Š”๋‹ค. 

 

2. Promise.prototype.catch

catch ๋ฉ”์„œ๋“œ๋Š” ํ•œ ๊ฐœ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(ํ”„๋กœ๋ฏธ์Šค๊ฐ€ rejected ์ƒํƒœ์ธ ๊ฒฝ์šฐ)๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ ๋ฐ›๋Š”๋‹ค.

catch ๋ฉ”์„œ๋“œ๋Š” then๊ณผ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.  

3. Promise.prototype.finally

finally ๋ฉ”์„œ๋“œ๋Š” ํ•œ ๊ฐœ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ ๋ฐ›๋Š”๋‹ค.

finally ๋ฉ”์„œ๋“œ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ํ”„๋กœ๋ฏธ์Šค์˜ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ์™€ ์ƒ๊ณผ์—†์ด ๋ฌด์กฐ๊ฑด ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋œ๋‹ค. 

 

๐Ÿ‘‰ finally ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœ๋ฏธ์Šค์˜ ์ƒํƒœ์™€ ์ƒ๊ด€์—†์ด ๊ณตํ†ต์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ์ฒ˜๋ฆฌ ๋‚ด์šฉ์ด ์žˆ์„ ๋•Œ ์œ ์šฉํ•˜๋‹ค. 

 

const promiseGet = url => {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.send();

    xhr.onload = () => {
      if (xhr.status === 200) {
        // ์„ฑ๊ณต์ ์œผ๋กœ ์‘๋‹ต์„ ์ „๋‹ฌ๋ฐ›์œผ๋ฉด resolve ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
        resolve(JSON.parse(xhr.response));
      } else {
        // ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด reject ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
        reject(new Error(xhr.status));
      }
    };
  });
};

// promiseGet ํ•จ์ˆ˜๋Š” ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
promiseGet('https://jsonplaceholder.typicode.com/posts/1')
  .then(res => console.log(res))
  .catch(err => console.error(err))
  .finally(() => console.log('Bye!'));


//์ฃผ์†Œ๋ฅผ ์ผ๋ถ€๋Ÿฌ ์ž˜๋ชป ์จ๋ด„

promiseGet('https://jsonplaceholder.typicode.com/post/1')
  .then(res => console.log(res))
  .catch(err => console.error(err))
  .finally(() => console.log('Bye!'));


โœ”๏ธ ํ”„๋กœ๋ฏธ์Šค์˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ

ํ”„๋กœ๋ฏธ์Šค์˜ ์—๋Ÿฌ์ฒ˜๋ฆฌ๋Š” ์ฃผ๋กœ catch ๋ฉ”์„œ๋“œ๋กœ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, catch ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋“  then ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ์ดํ›„์— ํ˜ธ์ถœํ•˜๋ฉด ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์—์„œ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ์™€ then ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ๊นŒ์ง€ ๋ชจ๋‘ ์บ์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

โœ”๏ธ ํ”„๋กœ๋ฏธ์Šค ์ฒด์ด๋‹

์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋‹ค๋ฉด ํ”„๋ผ๋ฏธ์Šค ์ฒด์ด๋‹(promise chaining)์„ ์ด์šฉํ•ด์„œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. 

ํ”„๋กœ๋ฏธ์Šค ์ฒด์ด๋‹์ด ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” promise.then์„ ํ˜ธ์ถœํ•˜๋ฉด ํ”„๋ผ๋ฏธ์Šค๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฐ˜ํ™˜๋œ ํ”„๋ผ๋ฏธ์Šค์—” ๋‹น์—ฐํžˆ .then์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์‚ฌ์šฉ
// GET ์š”์ฒญ์„ ์œ„ํ•œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜
const get = (url, callback) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.send();

  xhr.onload = () => {
    if (xhr.status === 200) {
      // ์„œ๋ฒ„์˜ ์‘๋‹ต์„ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ์ „๋‹ฌํ•˜๋ฉด์„œ ํ˜ธ์ถœํ•˜์—ฌ ์‘๋‹ต์— ๋Œ€ํ•œ ํ›„์† ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.
      callback(JSON.parse(xhr.response));
    } else {
      console.error(`${xhr.status} ${xhr.statusText}`);
    }
  };
};

const url = 'https://jsonplaceholder.typicode.com';

// id๊ฐ€ 1์ธ post์˜ userId๋ฅผ ์ทจ๋“
get(`${url}/posts/1`, ({ userId }) => {
  console.log(userId); // 1
  // post์˜ userId๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ user ์ •๋ณด๋ฅผ ์ทจ๋“
  get(`${url}/users/${userId}`, userInfo => {
    console.log(userInfo); // {id: 1, name: "Leanne Graham", username: "Bret",...}
  });
});
  • promise ์‚ฌ์šฉ
const url = 'https://jsonplaceholder.typicode.com';

// id๊ฐ€ 1์ธ post์˜ userId๋ฅผ ์ทจ๋“
promiseGet(`${url}/posts/1`)
  // ์ทจ๋“ํ•œ post์˜ userId๋กœ user ์ •๋ณด๋ฅผ ์ทจ๋“
  .then(({ userId }) => promiseGet(`${url}/users/${userId}`))
  .then(userInfo => console.log(userInfo))
  .catch(err => console.error(err));
  • async/await ์‚ฌ์šฉ
const url = 'https://jsonplaceholder.typicode.com';

(async () => {
  // id๊ฐ€ 1์ธ post์˜ userId๋ฅผ ์ทจ๋“
  const { userId } = await promiseGet(`${url}/posts/1`);

  // ์ทจ๋“ํ•œ post์˜ userId๋กœ user ์ •๋ณด๋ฅผ ์ทจ๋“
  const userInfo = await promiseGet(`${url}/users/${userId}`);

  console.log(userInfo);
})();

 

โœ”๏ธ Promise.all

Promise.all ๋ฉ”์„œ๋“œ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ๋ชจ๋‘ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. 

 

const requestData1 = () => new Promise(resolve => setTimeout(() => resolve(1), 3000));
const requestData2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000));
const requestData3 = () => new Promise(resolve => setTimeout(() => resolve(3), 1000));

// ์„ธ ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ
const res = [];
requestData1()
  .then(data => {
    res.push(data);
    return requestData2();
  })
  .then(data => {
    res.push(data);
    return requestData3();
  })
  .then(data => {
    res.push(data);
    console.log(res); // [1, 2, 3] ⇒ ์•ฝ 6์ดˆ ์†Œ์š”
  })
  .catch(console.error);

โžฅ ์„ธ ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์•ž์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋‹ค์Œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. 

์ฒซ๋ฒˆ์งธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— 3์ดˆ, ๋‘๋ฒˆ์งธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— 2์ดˆ, ์„ธ๋ฒˆ์งธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— 1์ดˆ๊ฐ€ ์†Œ์š”๋˜์„œ ์ด 6์ดˆ ์ด์ƒ์ด ์†Œ์š”๋œ๋‹ค. 

 

์•ž์„  ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์Œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ด๋•Œ Promise.all ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

const requestData1 = () => new Promise(resolve => setTimeout(() => resolve(1), 3000));
const requestData2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000));
const requestData3 = () => new Promise(resolve => setTimeout(() => resolve(3), 1000));

Promise.all([requestData1(), requestData2(), requestData3()])
  .then(console.log) // [ 1, 2, 3 ] ⇒ ์•ฝ 3์ดˆ ์†Œ์š”
  .catch(console.error);

โžฅ ์ฒซ๋ฒˆ์งธ ํ”„๋กœ๋ฏธ์Šค๋Š” 3์ดˆ ํ›„์— 1์„ resolveํ•˜๊ณ , ๋‘๋ฒˆ์งธ ํ”„๋กœ๋ฏธ์Šค๋Š” 2์ดˆ ํ›„์— 2์„ resolveํ•˜๊ณ , ์„ธ๋ฒˆ์งธ ํ”„๋กœ๋ฏธ์Šค๋Š” 1์ดˆ ํ›„์— 3์„ resolveํ•ด์„œ ์ด 3์ดˆ ์ด์ƒ์ด ์†Œ์š”๋œ๋‹ค. 

 

 

Promise.all ๋ฉ”์„œ๋“œ๋Š” ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์€ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ๋ชจ๋‘ fulfulled ์ƒํƒœ๊ฐ€ ๋˜๋ฉด ์ข…๋ฃŒํ•œ๋‹ค. 
Promise.all ๋ฉ”์„œ๋“œ๋Š” ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์€ ๋ฐฐ์—ด์˜ ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ํ•˜๋‚˜๋ผ๋„ rejected ์ƒํƒœ๊ฐ€ ๋˜๋ฉด ๋‚˜๋จธ์ง€ ํ”„๋กœ๋ฏธ์Šค๊ฐ€ fulfilled ์ƒํƒœ๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ์ฆ‰์‹œ ์ข…๋ฃŒํ•œ๋‹ค. 
Promise.all([
  new Promise((_, reject) => setTimeout(() => reject(new Error('Error 1')), 3000)),
  new Promise((_, reject) => setTimeout(() => reject(new Error('Error 2')), 2000)),
  new Promise((_, reject) => setTimeout(() => reject(new Error('Error 3')), 1000))
])
  .then(console.log)
  .catch(console.log); // Error: Error 3

 

 

๐Ÿ‘ฉ‍๐Ÿ’ป ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive๋ฅผ ์ •๋…ํ•˜๊ณ  ์ œ๊ฐ€ ์ดํ•ดํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค ๐Ÿ‘ฉ‍๐Ÿ’ป