하다보니

프로미스 개념부터 활용까지 본문

프로그래밍 언어/JavaScript

프로미스 개념부터 활용까지

claire 2022. 1. 22. 14:09

promise - 자바스크립트에서 제공하는 비동기를 간편하게 처리할 수 있도록 도와주는 오브젝트이다.

promise는 정해진 장시간의 기능을 수행하고 나서 정상적으로 기능이 수행되어졌다면 성공 메세지와 함께 처리된 결과값을 전달해준다. 에러가 나면 에러를 전달.

promise는 자바 스크립트 안에 내장되어 있는 오브젝트 이다. 비동기적인 작업을 수행할 때 콜백함수 대신에 유용하게 사용할 수 있는 오브젝트이다.

  1. state : 프로세스가 heavy한 operation을 수행하고 있는 중인지 기능 수행을 완료한 후 성공인지 실패인지 상태에 대해 이해하는 것이 중요하다.  operation이 수행 중일 때는 pending상태이고 이것을 성공적이게 끝내게 되면 fulfilled state가 된다. 만약 파일을 찾을 수 없거나 네트워크에 문제가 생기면 rejected state가 된다.
  2. producer와 consumer의 차이점을 안다. - 데이터를 제공하는 producer와 데이터를 소비하는 consumer.
'use strict';

// Promise is a JavaScript object for asynchronous operation.
// State: pending -> fulfilled or rejected   
//operation을 수행중이면 pending 상태이고 완벽하게 완료하면 fulfilled 상태가 된다.
//아니면 파일을 찾을 수가 없거나 네트워크 문제가 생기면 rejected 상태가 된다.  

// Producer vs Consumer

// 1. Producer
// when new Promise is created, the executor runs automatically.
//프로미스를 만들면 executor가 바로 자동으로 실행이 된다. 
//프로미스는 클래스라 new로 생성. 
//resolve는 기능을 정상적으로 수행해서 마지막에 최종 데이터를 전달하는 콜백함수.
//reject는 기능을 수행하다가 중간에 문제가 생기면	호출할 reject

const promise = new Promise((resolve, reject) => {
  // doing some heavy work (network, read files) - 프로미스 안에서 헤비한 작업을 한다. 
  console.log('doing something...');
  
  setTimeout(() => {
    resolve('ellie');
    // reject(new Error('no network'));
  }, 2000);
});

// 2. Consumers: then, catch, finally로 값을 받아올 수 있다. 
promise //
  .then(value => {	//프로미스가 정상적으로 실행이 되어서 resolve로 전달한 값이 들어온다. 
    console.log(value);
  })
  //에러 발생시 실행할 것. then은 프로미스를 리턴하기 때문에 chaining으로 catch를 또 호출할 수 있는 것이다. 
  .catch(error => {	
    console.log(error);
  })
  //fianlly는 성공 실패에 상관없이 무조건 호출되는 것. 
  .finally(() => {
    console.log('finally');
  });

// 3. Promise chaining
const fetchNumber = new Promise((resolve, reject) => {

//실제로 서버통신 해야하는 부분. 
  setTimeout(() => resolve(1), 1000);
});

fetchNumber
  .then(num => num * 2)
  .then(num => num * 3)
  //then은 프로미스를 전달할 수도 있다. 
  .then(num => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(num - 1), 1000);
    });
  })
  .then(num => console.log(num));			//출력:5


// 4. Error Handling
const getHen = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve('🐓'), 1000);
  });
const getEgg = hen =>
  new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error(`error! ${hen} => 🥚`)), 1000);
  });
const cook = egg =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => 🍳`), 1000);
  });

getHen()
	.then(hen=>getEgg(hen))
    .then(egg=>cook(egg))
    .then(meal=>console.log(meal));
//깂을 받아와 바로 호출하는 경우에는 밑의 형태처럼 생략이 가능하다. 
getHen() //(이것을 붙이면 prettier에서 한줄로 고쳐주는 것을 막을 수 있다. 
  .then(getEgg)
  //getEgg에서 나는 오류를 바로 처리하고 싶을 때는 바로 다음에 catch를 쓰면 된다. 
  .catch(error=>{
  	return 'a';
   })
  .then(cook)
  .then(console.log)
  .catch(console.log);

저번 시간에 본 콜백지옥을 프로미스로 수정해본다. 

// Callback Hell example 수정
class UserStorage {
  loginUser(id, password) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (
          (id === 'ellie' && password === 'dream') ||
          (id === 'coder' && password === 'academy')
        ) {
          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);
    });
  }

}

// Original code from Youtube course
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your passrod');
userStorage
  .loginUser(id, password)
  .then(userStorage.getRoles)
  .then(user => alert(`Hello ${user.name}, you have a ${user.role} role`))
  .catch(console.log);

 

출처 : 드림코딩 엘리