본문 바로가기

프로그래밍/웹

자바스크립트 Promise

반응형

 

 

Promise

  • 자바스크립트에서 사용하는 비동기 코드 처리를 위한 객체
  • 어떤 기능이 실행되어 정상적으로 동작하면, 성공 메시지와 처리 결과를 전달
  • 기능 수행 시 예상치 못한 문제가 발생하면 에러를 전달
  • State: pending(보류) → fulfilled(성공) or rejected(실패) or settled(완료)
  • 비동기 처리 성공 시 resolve, 실패 시 reject 함수 호출
  • Promise 객체의 후속 처리 메소드(then, catch)를 통해 실행된 결과 전달

Producer(생산자)
  • 새 프로미스가 생성되면 executor라는 콜백함수가 자동 실행됨
  • 프로미스 내의 resolve 함수가 존재하지 않으면 무한 pending 상태
  • 아래 예제는 2초간 기능 수행 후 resolve라는 함수를 호출하면서 콘솔에 'ellie' 출력
 const promise = new Promise((resolve, reject) => {
   // 시간이 오래 걸리는 무거운 처리 (network, read files ..)
   console.log(`doing something...`);
   setTimeout(() => {
     resolve(`ellie`); // 성공 하면
     // reject(new Error(`no network`)); // 실패 하면
   }, 2000);
 });


Consumer(소비자)
  • try, catch, finally
  • value 파라미터로 resolve 결과 값을 전달받는다.
 promise
   .then((value) => {
     console.log(value);
   })
   .catch(error => {
     console.log(error);
   })
   .finally(() => { // 성공하든 실패하든 마지막에 실행됨
     console.log(`finally`);
   })


Promise chaining

  • then은 다음 체인으로 값을 바로 전달 가능
  • 리턴으로 Promise를 전달 가능
 const fetchNumber = new Promise((resolve, reject) => {
   setTimeout(() => resolve(1), 1000);
 });
 
 fetchNumber
   .then(num => {
     return num * 2; // > 2
   })
   .then(num => num * 3) // > 6
   .then(num => { // > 5
     return new Promise((resolve, reject) => {
       setTimeout(() => resolve(num - 1), 1000);
     });
   })
   .then(num => console.log(num)); // > 5


Error handling

  • catch로 error를 핸들링
  • error가 발생해도 catch를 이용하면 전체적인 Promise 체인에 문제가 발생하지 않도록 예외처리 가능
 const getHen = () => {
   return new Promise((resolve, reject) => {
     setTimeout(() => resolve(`🐓`), 1000);
     // setTimeout(() => reject(new Error(`error! 🐓`)), 1000);
   });
 };
 const getEgg = hen =>
   new Promise((resolve, reject) => {
     // setTimeout(() => resolve(`${hen} => 🥚`), 1000);
     setTimeout(() => reject(new Error(`error! ${hen} => 🥚`)), 1000);
   });
 const cook = (egg) => 
   new Promise((resolve, reject) => {
     setTimeout(() => resolve(`${egg} => 🍗`), 1000);
     // setTimeout(() => reject(new Error(`error! ${egg} => 🍗`)), 1000);
   });
 
 getHen()
   .catch(error => {
     console.log(error);
     return `💀`; // 예외처리
   })
   .then(hen => getEgg(hen))
   .catch(error => {
     console.log(error);
     return `💀`; // 예외처리
   })
   .then(egg => cook(egg))
   .catch(error => {
     console.log(error);
     return `💀`; // 예외처리
   })
   .then(result => console.log(result))
   .catch(error => {
     console.log(error); // 예외처리
   })
 
 // 원본 코드
 // getHen()
 //   .then((hen) => {
 //     return getEgg(hen);
 //   })
 //   .then((egg) => {
 //     return cook(egg);
 //   })
 //   .then((result) => {
 //     console.log(result);
 //   })
 
 // 파라미터가 1개일때 함수이름만 쓰면, 암묵적으로 함수의 매개변수로 전달 됨.
 // getHen()
 //   .then(getEgg)
 //   .then(cook)
 //   .then(console.log);


callback to Promise

 'use strict';
 
 class UserStorage {
   loginUser(id, password) {
     return new Promise((resolve, reject) => {
       setTimeout(() => {
         if (
           (id === `ellie` && password === `123`) ||
           (id === `gunwoo` && password === `1104`)
         ) {
           resolve(id);
         } else {
           reject(new Error(`not found`));
         }
       }, 2000);
     });
   }
 
   getRoles(user) {
     return new Promise((resolve, reject) => {
       setTimeout(() => {
         if (user === `ellie`) resolve({ name: `ellie`, role: `admin` });
         else reject(new Error(`no access`));
       }, 1000);
     });
   }
 }
 
 const id = prompt(`enter your id`);
 const password = prompt(`enter your password`);
 
 const userStorage = new UserStorage();
 userStorage
   .loginUser(id, password)
   .then(user =>  userStorage.getRoles(user))
   .then(userInfo => alert(`name: ${userInfo.name}, role: ${userInfo.role}`))
   .catch(error => console.log(error));

참고 : https://www.youtube.com/watch?v=tJieVCgGzhs&list=PLv2d7VI9OotTVOL4QmPfvJWPJvkmv6h-2&index=2


반응형