๐Ÿ’ป Development/JavaScript

Promise, async, await

ahyeon7 2023. 1. 24. 02:51

๐Ÿ“Œ Promise

โœจ new Promise

Promise๋Š” class์ด๊ธฐ ๋•Œ๋ฌธ์— new ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด Promise ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋˜ํ•œ Promise๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ฝœ๋ฐฑ ํ•จ์ˆ˜(executor)๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›๋Š”๋ฐ ์ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” resolve, reject ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›๋Š”๋‹ค.

Promise ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด executor๋Š” ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜๊ณ  ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ๋“ค์ด ์ž‘๋™๋œ๋‹ค. ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด resolve ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ์—๋Š” reject ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค.

let promise = new Promise((resolve, reject) => {
	// 1. ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒฝ์šฐ
	// resolve์˜ ์ธ์ž์— ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
	resolve(value);

	// 2. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ
	// reject์˜ ์ธ์ž์— ์—๋Ÿฌ๋ฉ”์„ธ์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
	reject(error);
});

โœจ Promise ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ

new Promise๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” Promise ๊ฐ์ฒด๋Š” state, result ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ–๋Š”๋‹ค. ํ•˜์ง€๋งŒ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ณ  .then, .catch, .finally ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

โœจ State

๊ธฐ๋ณธ ์ƒํƒœ๋Š” pending(๋Œ€๊ธฐ) ์ž…๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ฝœ๋ฐฑ ํ•จ์ˆ˜(executor)๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ž‘๋™ํ–ˆ๋‹ค๋ฉด fulfilled (์ดํ–‰)๋กœ ๋ณ€๊ฒฝ์ด ๋˜๊ณ , ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด rejected (๊ฑฐ๋ถ€)๊ฐ€ ๋œ๋‹ค.

โœจ Result

์ฒ˜์Œ์€ undefined ์ด๋‹ค. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ฝœ๋ฐฑ ํ•จ์ˆ˜(executor)๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ž‘๋™ํ•˜์—ฌresolve(value)๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด value๋กœ, ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ reject(error)๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด error๋กœ ๋ณ€ํ•œ๋‹ค.

๐Ÿ“Œ then, catch, finally

โœจ Then

executor์— ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ๋“ค์ด ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด resolve ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  .then ๋ฉ”์„œ๋“œ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ .then ์•ˆ์—์„œ ๋ฆฌํ„ดํ•œ ๊ฐ’์ด Promise๋ฉด Promise์˜ ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ result๋ฅผ ๋‹ค์Œ .then ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋ฐ›์•„์˜ค๊ณ , Promise๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋ฆฌํ„ดํ•œ ๊ฐ’์„ .then ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

let promise = new Promise((resolve, reject) => {
	resolve("์„ฑ๊ณต");
});

promise.then(value => {
	console.log(value);
	// "์„ฑ๊ณต"
})

โœจ Catch

executor์— ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ๋“ค์ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ์—๋Š” reject ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  .catch ๋ฉ”์„œ๋“œ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

let promise = new Promise(function(resolve, reject) {
	reject(new Error("์—๋Ÿฌ"))
});

promise.catch(error => {
	console.log(error);
	// Error: ์—๋Ÿฌ
})

โœจ Finally

executor์— ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ๋“ค์˜ ์ •์ƒ ์ฒ˜๋ฆฌ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด .finally ๋ฉ”์„œ๋“œ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

let promise = new Promise(function(resolve, reject) {
	resolve("์„ฑ๊ณต");
});

promise
.then(value => {
	console.log(value);
	// "์„ฑ๊ณต"
})
.catch(error => {
	console.log(error);
})
.finally(() => {
	console.log("์„ฑ๊ณต์ด๋“  ์‹คํŒจ๋“  ์ž‘๋™!");
	// "์„ฑ๊ณต์ด๋“  ์‹คํŒจ๋“  ์ž‘๋™!"
})

โœจ Promise chaining

Promise chaining๊ฐ€ ํ•„์š”ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ง„ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์ด๋‹ค. Promise chaining์ด ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” .then, .catch, .finally ์˜ ๋ฉ”์„œ๋“œ๋“ค์€ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ .then์„ ํ†ตํ•ด ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ณ , ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ .catch ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋œ๋‹ค.

let promise = new Promise(function(resolve, reject) {
	resolve('์„ฑ๊ณต');
	...
});

promise
  .then((value) => {
    console.log(value);
    return '์„ฑ๊ณต';
  })
  .then((value) => {
    console.log(value);
    return '์„ฑ๊ณต';
  })
  .then((value) => {
    console.log(value);
    return '์„ฑ๊ณต';
  })
  .catch((error) => {
    console.log(error);
    return '์‹คํŒจ';
  })
  .finally(() => {
    console.log('์„ฑ๊ณต์ด๋“  ์‹คํŒจ๋“  ์ž‘๋™!');
  });

โœจ Promise.all()

const promiseOne = () => new Promise((resolve, reject) => setTimeout(() => resolve('1์ดˆ'), 1000));
const promiseTwo = () => new Promise((resolve, reject) => setTimeout(() => resolve('2์ดˆ'), 2000));
const promiseThree = () => new Promise((resolve, reject) => setTimeout(() => resolve('3์ดˆ'), 3000));

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

์•ž์„œ ๋ฐฐ์šด Promise chaining์„ ์‚ฌ์šฉํ–ˆ์„ ๊ฒฝ์šฐ๋Š” ์ฝ”๋“œ๋“ค์ด ์ˆœ์ฐจ์ ์œผ๋กœ ๋™์ž‘๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด 6์ดˆ์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๊ฒŒ ๋œ๋‹ค. ๋˜ํ•œ, ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋˜๋Š” ํ˜„์ƒ๋„ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

// ๊ธฐ์กด
const result = [];
promiseOne()
  .then(value => {
    result.push(value);
    return promiseTwo();
  })
  .then(value => {
    result.push(value);
    return promiseThree();
  })
  .then(value => {
    result.push(value);
   console.log(result);  
	 // ['1์ดˆ', '2์ดˆ', '3์ดˆ']
  })

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋“ค์„ Promise.all()์„ ํ†ตํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. Promise.all()์€ ๋น„๋™๊ธฐ ์ž‘์—…๋“ค์„ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•œ๋‹ค. ๋”ฐ๋ผ์„œ 3์ดˆ ์•ˆ์— ๋ชจ๋“  ์ž‘์—…์ด ์ข…๋ฃŒ๋œ๋‹ค. ๋˜ํ•œ Promise chaining๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ณด๋‹ค ๊ฐ„๊ฒฐํ•ด์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

// promise.all
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
  .then((value) => console.log(value))
  // ['1์ดˆ', '2์ดˆ', '3์ดˆ']
  .catch((err) => console.log(err));

์ถ”๊ฐ€์ ์œผ๋กœ Promise.all์€ ์ธ์ž๋กœ ๋ฐ›๋Š” ๋ฐฐ์—ด์— ์žˆ๋Š” Promise ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด ๋‚˜๋จธ์ง€ Promise์˜ state์™€ ์ƒ๊ด€์—†์ด ์ฆ‰์‹œ ์ข…๋ฃŒ๋œ๋‹ค. ์•„๋ž˜์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด 1์ดˆ ํ›„์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  Error: ์—๋Ÿฌ1์ด ๋ฐ˜ํ™˜๋œ ํ›„๋กœ๋Š” ๋” ์ด์ƒ ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ  ์ข…๋ฃŒ๋œ๋‹ค.

Promise.all([
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('์—๋Ÿฌ1'))), 1000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('์—๋Ÿฌ2'))), 2000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('์—๋Ÿฌ3'))), 3000),
])
	.then((value) => console.log(value))
  .catch((err) => console.log(err));
	// Error: ์—๋Ÿฌ1

โœจ async ⇒ ํ•จ์ˆ˜๋ฅผ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ ์„ ์–ธํ•˜๋Š” ํ‚ค์›Œ๋“œ

async function hello() {
	return 'Hey guy!';
}

ํ•จ์ˆ˜๋ฅผ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ ์„ ์–ธํ•˜๋ฉด ํ•จ์ˆ˜๋Š” ์ž๋™์œผ๋กœ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Promise๋กœ ๋ฐ˜ํ™˜ํ•˜๋ผ๊ณ  ํ•˜์ง€ ์•Š์•„๋„ ์ž๋™์œผ๋กœ ์•”์‹œํ•œ๋‹ค.

async function hello() {
}

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

์ด๋Š”, ์•ž์„œ ๋งํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด ํ•จ์ˆ˜๋Š” ์ž๋™์œผ๋กœ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ฆ๋ช…ํ•œ๋‹ค.

const login = async (username, password) => {
  if (!username || !password) throw '๊ฑธ์–ด๋ด ์œ„์—„ ๋ž” ์–ด ๋ผ์ด์˜น...';
  if (password === 'antititi') return '์•ˆํ‹ฐํ‹ฐํ‹ฐํ‹ฐ!';
  throw '๊ฑธ์–ด๋ด ์œ„์—„ ๋ž” ์–ด ๋ผ์ด์˜น...';
};

login('user', 'antititi')
  .then((msg) => {
    console.log(`WELCOME! ${msg}`);
  })
  .catch((e) => {
    console.log(`์‹คํŒจ... ${e}`);
  });
const login = async (username, password) => {
  if (!username || !password) throw '๊ฑธ์–ด๋ด ์œ„์—„ ๋ž” ์–ด ๋ผ์ด์˜น...';
  if (password === 'antititi') return '์•ˆํ‹ฐํ‹ฐํ‹ฐํ‹ฐ!';
  throw '๊ฑธ์–ด๋ด ์œ„์—„ ๋ž” ์–ด ๋ผ์ด์˜น...';
};

login('user', 'anti')
  .then((msg) => {
    console.log(`WELCOME! ${msg}`);
  })
  .catch((e) => {
    console.log(`์‹คํŒจ... ${e}`);
  });

โœจ await ⇒ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์“ฐ๋ฉด์„œ ๋™๊ธฐ์ ์œผ๋กœ ๋ณด์ด๊ฒŒ ํ•ด ์ค€๋‹ค.

๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•˜๋Š” ๊ฒƒ! Promise๊ฐ€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ ์œ„ํ•ด ๋น„๋™๊ธฐ ํ•จ์ˆ˜์˜ ์‹คํ–‰์„ ์ผ์‹œ ์ •์ง€ ์‹œํ‚จ๋‹ค. ๋น„๋™๊ธฐ ํ•จ์ˆ˜์—์„œ ์ ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— async์™€ await๋Š” ํ•œ์Œ์ด๋‹ค!