Javascript - Promise

Promise

promise๋Š” ๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ์—์„œ ๋งˆ์น˜ ๋™๊ธฐ ๋ฉ”์„œ๋“œ์ฒ˜๋Ÿผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋Š” ์•Š๊ณ , ๋Œ€์‹  ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ ๋ฏธ๋ž˜์˜ ์–ด๋–ค ์‹œ์ ์— ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

**์ƒํƒœ **

  • pending(๋Œ€๊ธฐ) : ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋กœ์ง์ด ์•„์ง ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ์ƒํƒœ
  • fulfilled(์ดํ–‰) : ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์–ด ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ค€ ์ƒํƒœ
  • rejected(๊ฑฐ๋ถ€) : ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ์ƒํƒœ

1. Producer (Promise ๋งŒ๋“ค๊ธฐ)

  • ์ƒˆ๋กœ์šด Promise๊ฐ€ ๋งŒ๋“ค์–ด์งˆ ๋•Œ๋Š” ์ „๋‹ฌํ•œ executorํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ ์‹คํ–‰์ด ๋œ๋‹ค.
const promise = new Promise((resolve, reject) => {
  // doing some heavy work(networt, read files)
  console.log("doing something...");
  setTimeout(() => {
    resolve("hello!");
  }, 2000);
});

โ€˜doing somethingโ€ฆโ€˜์ดํ›„ 2์ดˆ ๋’ค์— hello!๊ฐ€ ์ฝ˜์†”์— ์ฐํžŒ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

2. Consumers : then, catch, finally (Promise ์‚ฌ์šฉํ•˜๊ธฐ)

  • then : promise ๊ฐ€ ์ข…๋ฃŒ๊ฐ€ ๋˜๋ฉด resolve ์— ๋“ค์–ด๊ฐ„ ๊ฐ’์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • catch : reject ๋œ ๊ฒฝ์šฐ์—๋Š” then ์œผ๋กœ ๋ฐ›์„ ๊ฒฝ์šฐ, ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ ์ด ์—๋Ÿฌ๋ฅผ catch๋กœ ์žก์„ ์ˆ˜ ์žˆ๋‹ค.
  • finally : ์„ฑ๊ณต๊ณผ ์‹คํŒจ์™€ ๊ด€๊ณ„์—†์ด ๋ฌด์กฐ๊ฑด ๋งˆ์ง€๋ง‰์— ํ˜ธ์ถœ๋˜์–ด์ง„๋‹ค.
const promise = new Promise((resolve, reject) => {
  // doing some heavy work(networt, read files)
  console.log("doing something...");
  setTimeout(() => {
    reject(new Error("no network"));
  }, 2000);
});
promise //
  .then((value) => {
    console.log(value);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("finally");
  });

3. Promise chaining (Promise ์—ฐ๊ฒฐํ•˜๊ธฐ)

const fetchNuber = new Promise((resolve, reject) => {
  setTimeout(() => resolve(1), 1000);
});
//1์ดˆ ์žˆ๋‹ค๊ฐ€ 1๋ฅผ ์ „๋‹ฌ

fetchNuber //
  .then((num) => num * 2) // 1*2 = 2
  .then((num) => num * 3) // 2*3 = 6
  .then((num) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(num - 1), 1000); //6-1 = 5
    });
  })
  .then((num) => console.log(num));

then์€ ๊ฐ’์„ ๋ฐ”๋กœ ์ „๋‹ฌํ• ์ˆ˜๋„ ์žˆ๊ณ  Promise๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 2์ดˆ์˜ ์‹œ๊ฐ„ ์†Œ์š” ๋’ค 5๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

4. ์˜ค๋ฅ˜์ฒ˜๋ฆฌ

const getHen = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve("๐Ÿ“"), 1000);
  });
const getEgg = (hen) =>
  new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error(`${hen} => ๐Ÿฅš`)), 1000);
  });
const cook = (egg) =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => ๐Ÿณ`), 1000);
  });

์ด 3๊ฐ€์ง€์˜ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜๋กœ, 1์ดˆ ์žˆ๋‹ค๊ฐ€ ๐Ÿ“์„ ๋ฆฌํ„ด, ๐Ÿ“์„ ๋ฐ›์•„์™€์„œ ๐Ÿฅš๋ฅผ ๋ฆฌํ„ด, ๐Ÿฅš๋ฅผ ๋ฐ›์•„์™€์„œ ๐Ÿณ๋ฅผ ๊ฐ€์ •ํ•˜์˜€๋‹ค.

getHen()
  .then((hen) => getEgg(hen))
  .then((egg) => cook(egg))
  .then((cook) => console.log(cook));

// โฌ‡๏ธ ํ•œ๊ฐ€์ง€๋งŒ ๋ฐ›์•„์„œ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ์ƒ๋žต์ด ๊ฐ€๋Šฅํ•˜์—ฌ ์งง๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
getHen() //
  .then(getEgg)
  .then(cook)
  .then(console.log);

์—๋Ÿฌ๋ฅผ ์žก์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๋ฉ”์„ธ์ง€๊ฐ€ ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚œ ๋’ค ๋งจ ๋’ค์— catch๋ฅผ ํ†ตํ•ด ์—๋Ÿฌ๋ฅผ ์žก์•„์ฃผ๊ฒŒ ๋˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์ง€๋งŒ ์—๋Ÿฌ๊ฐ€ ๋งจ ์•„๋ž˜๋กœ ์ „๋‹ฌ๋˜๋ฉด์„œ catch๊ฐ€ ์žกํžŒ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

getHen() //
  .then(getEgg)
  .then(cook)
  .then(console.log)
  .catch(console.log);

getHen() //
  .then(getEgg)
  .catch((error) => {
    return "๐Ÿฅ–";
  })
  .then(cook)
  .then(console.log)
  .catch(console.log);

๊ณ„๋ž€์„ ๋ฐ›์•„์˜ฌ ๋•Œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค๋ฉด, ๋‹ค๋ฅธ ๊ฑธ๋กœ ๋Œ€์ฒดํ•ด์„œ Promise ์ฒด์ธ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

โœจ ์ฝœ๋ฐฑ์ง€์˜ฅ -> Promise ์ด์šฉํ•˜๊ธฐ

์ง€๋‚œ ์‹œ๊ฐ„์— ์ž‘์„ฑํ•œ ์ฝœ๋ฐฑ์ง€์˜ฅ์„ Promise๋ฅผ ์ด์šฉํ•˜์—ฌ ๊น”๋”ํ•˜๊ฒŒ ์ฝ”๋“œ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์žˆ๋‹ค.

class UserStorage {
  loginUser(id, password) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (
          (id === "hyesung" && password === "qwerty") ||
          (id === "coder" && password === "zxcvb")
        ) {
          resolve(id);
        } else {
          reject(new Error("not found"));
        }
      }, 2000);
    });
  }

  getRoles(user) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (user === "hyesung") {
          resolve({ name: "hyesung", role: "admin" });
        } else {
          reject(new Error("no access"));
        }
      }, 1000);
    });
  }
}

const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your password");
userStorage
  .loginUser(id, password)
  .then((user) => userStorage.getRoles(user))
  .then((user) => alert(`Hello ${user.name}, you have a ${user.role} role`))
  .catch(console.log);

์ถœ์ฒ˜ : ๋“œ๋ฆผ์ฝ”๋”ฉ by ์—˜๋ฆฌ https://youtu.be/JB_yU6Oe2eE