Promise

Joy·2023년 1월 2일
0

ES6

목록 보기
4/5

자바스크립트는 동기식 언어로 한 번에 하나의 작업을 수행한다.
동기란? 프로그램이 작성된 순서대로 실행되는 것
비동기란? 특정코드가 끝날 때까지 기다렸다가 다음 코드를 진행하는 것이 아닌
코드의 진행이 멈추지 않고 다음 코드를 먼저 실행하는 것이다.

  • 동기
    -- 직렬적(순서대로)으로 작업을 수행한다.
    즉, 요청을 보낸 후 응답을 받아야만 다음동작이 이루어지는 방식이다.
    어떠한 작업을 처리할 동안 다음의 나머지 작업들은 대기한다.
  • 비동기
    -- 요청을 보낸 후 응답의 수락 여부와는 상관없이 다음 작업이 동작하는 방식이다.
    a작업을 실행하는 시간동안 b작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있다.

콜백함수와 Promise

1. 콜백함수

콜백함수란? 함수 자체를 인자로 전달하는 방식으로 함수 안에서 실행되는 또 다른 함수이다.
즉, 파라미터로 변수가 아닌 함수를 전달하는 것을 말한다.

보통 함수를 선언한 뒤에 함수 타입 파라미터를 맨 마지막에 하나 더 선언해 주는 방식으로 정의한다.
처리가 끝나면 파라미터로 전달 받은 함수를 실행한다.

  function mainFunc(param1, param2, callbackFunc) {
    // ... 처리 내용 작성
    callbackFunc(result);
  }

콜백함수의 대표적인 사용 예로는 setTimeout함수가 있다.
브라우저에 요청을 보냈던 것이 처리가 되면 이를 실행할 수 있도록 나중에 다시 불러야 하는데, 이 불러달라는 것에 착안하여 Call Back 함수라고 이름이 붙었다.

	console.log('1');
    setTimeout(function(){
    	console.log('2');
    },1000);
    console.log('3');

1->3->2의 순서로 실행된다.

콜백함수를 남용하면 코드의 깊이가 깊어지며 가독성이 떨어지고 오류를 찾기도 어려워질 수 있다.

const obj = {
  loginUser : function(id, password, onSuccess, onError){
    setTimeout(()=>{
      if (
        (id === 'joy' && password === 'joyy') ||
        (id === 'yeon' && password === 'yeonn')
      ) {
        onSuccess(id)
      }
      else {
        onError(new Error('not Found'))
      }
    },2000)
  },
  getRoles : function(id, onSuccess, onError){
        setTimeout(() => {
      if (id === 'joy') {
        onSuccess({ name: 'joy', role: 'admin' })
      } else {
        onError(new Error('No Access'))
      }
    }, 1000)
  }
}
// 구현할 프로세스
// 1. 사용자에게 id, password 입력받기
// 2. 로그인
// 3. 로그인 성공 시 받아온 id로 role 받아오기
// 4. 성공적으로 role을 받아오면 name과 role 출력

let id = prompt("id를 입력해주세요.");
let password = prompt("password를 입력해주세요.");

obj.loginUser(
  id,
  password,
  // loginUser 메소드의 onSuccess 콜백함수 전달 === getRoles함수 호출
  (id) => {   
    obj.getRoles(
      id,
      // getRoles 메소드의 onSuccess 콜백함수 전달
      (userWithRole) => {
        alert(
          `Hello ${userWithRole.name}! you have a ${userWithRole.role} role. `
        );
      },
      // getRoles 메소드의 onError 콜백함수 전달
      (error) => {
        console.log("no access");
      }
    );
  },
  // loginUser 메소드의 onError 콜백함수 전달
  (error) => {    
    console.log("error");
  }
);

obj객체에서 id, password 를 받아온다.
입력을 받아와 로그인에 성공하면 onSucccess(id) 를 통해 Roles, 역할을 요청하게 된다. (getRoles)
역할을 받아 올 수 있다면, 사용자의 객체(이름, 역할이 들어있는)를 보이게 한다.

  • 가독성이 떨어진다.
  • 에러를 찾기가 힘들다.

이런 콜백지옥을 해결하기 위해 Promise나 async/await를 사용할 수 있다.

2. Promise

ES6에서는 비동기 처리를 위한 또 다른 패턴으로 Promise를 도입했다.
Promise 는 자바스크립트에서 제공하는 비동기를 간편하게 처리할 수 있게 도와주는 객체이다.
작업 결과 따라 성공 또는 실패를 리턴하며 결과 값을 전달 받을 수 있다.
Promise는 비동기 작업을 수행 할 콜백함수를 인자로 전달 받는다.(resolve(성공), reject(실패))

	const 변수명 = new Promise((resolve,reject) => {
    	// resolve('');
        // reject('');
    });

Promise 객체는 state(상태)와 result(결과)를 프로퍼티로 갖는다.

Promise의 3가지 상태

  • Pending(대기):비동기 처리 로직이 아직 완료되지 않은 대기상태
  • Fulfilled(이행/성공):비동기 처리 로직이 완료된 후 결과 값을 반환 한 상태
  • Rejected(실패):비동기 처리 로직이 실패하거나 오류가 발생한 상태

Pending -> fulfilled가 되면 result는 resolve(value) 즉, resolve함수로 전달된 값이 된다.
Pending -> rejected가 되면 result는 reject(error) 즉, reject 함수로 전달된 error가된다.
promise의 상태가 fulfilled가 되면 then()을 이용하여 처리 결과 값을 받을 수 있고, rejected가 되면 catch()로 실패한 처리 결과 값을 받을 수 있다.

	const 변수명 = new Promise( (resolve, reject) => {
    	setTimeout(() => {
        	resolve('OK')
        },1000)
    });
    변수명.then((value) => {
      console.log(value);
    });

promise는 callback 패턴과는 다르게, 에러 상태를 관리함으로써 에러 처리가 가능해졌다.

	const promise1 = new Promise( (resolve, reject) => {
    	setTimeout(() => {
          if('1' == '1'){
            resolve('ok');
          } else{
              reject('error');
          }
        },1000)
    });
    promise1.then((value) => {
      console.log(value);
    });
    promise1.catch((value) => {
      console.log(value);
    });

조건문이 '참'이 되면 resolve로 then()이 실행되고,
그렇지 않으면 catch()가 실행된다.

프로미스는 후속 처리 메서드를 체이닝 하여 여러 개의 프로미스를 연결하여 사용할 수 있다.

const promise1 = () => new Promise((resolve, reject) => {
  setTimeout(() => {resolve("🥚")},1000)
});
const promise2 = (step1) => new Promise((resolve, reject) => {
  setTimeout(() => {resolve(`${step1} -> 🐣`)},1000)
});
const promise3 = (step2) => new Promise((resolve, reject) => {
  setTimeout(() => {resolve(`${step2} -> 🐥`)},1000)
});

promise1() //
.then((step1) => promise2(step1))
.then((step2) => promise3(step2))
.then((result) => console.log(result))

// 🥚 -> 🐣 -> 🐥
profile
🐣

0개의 댓글