[완강 챌린지] 웹 프론트엔드를 위한 자바스크립트 첫 걸음 : section3-4. promise

const job = '프론트엔드';·2023년 6월 25일
1
post-thumbnail

비동기처리

예시코드)

함수를 호출할 때, 1. 출력할 단어 2. 단어를 출력하는 함수 두 가지를 인수를 넘겨줌

실행결과 ) workD, workB, workA, workC 순서대로 출력

응용) workA에서 매개변수로 받은 값에 5를 더하고, 그 결괏값을 workB에서 전달받아 다시 3을 빼고, 다시 그 결괏값에 10 더하는 workC 함수로 코드를 변경

const workA = (value, callback) => {
  setTimeout(() => {
    callback(value + 5);
  }, 5000);
};
const workB = (value, callback) => {
  setTimeout(() => {
    callback(value - 3);
  }, 3000);
};
const workC = (value, callback) => {
  setTimeout(() => {
    callback(value + 10);
  }, 10000);
};
const workD = (value, callback) => {
  callback(value);
};

workA(10, (resA) => {
  console.log(`1. ${resA}`);
  workB(resA, (resB) => {
    console.log(`2. ${resB}`);
    workC(resB, (resC) => {
      console.log(`3. ${resC}`);
    });
  });
});
workD("workD", (res) => {
  console.log(res);
});

콜백지옥 !

비동기 함수의 결괏값을 또 다른 비동기 함수에서 사용하기 위해, 이렇게 콜백함수 안에 콜백함수를 전달하는 방식으로 전달하게 되면?
가독성이 매우 좋지 않은 코드가 되어 많은 오류를 발생시킨다 !

Promise 객체

자바스크립트의 비동기 작업을 조금 더 쉽게 !

프로미스 객체 생성

const executor = (resolve,reject) => {
}
const promise = new Promise(executor);
  • new 키워드로 생성자를 생성
  • 인수로 excecutor라는 실행함수를 전달(필수)
  • executor 함수는 프로미스 객체를 생성함과 동시에 실행되는 실행함수

resolve, reject

  • resolve와 reject은 자바스크립트에서 자체적으로 제공하는 콜백함수
  • executor는 비동기처리가 성공하면 resolve를, 실패한다면 reject를 호출

프로미스 내부 프로퍼티(state, result)

  • 프로미스 객체 초기: 대기 상태(pending) / undefined값
  • executor 호출하는 콜백함수에 따라
  • state / result가 변화
  • executor가 실행되고, 처음엔 대기 상태에 있다가, resolve가 호출 될 경우 프로미스의 state를 fulfilled(성공)로 변경하고, reject가 호출 될 경우 상태를 rejected(실패)로 변경
  • result 값은 처음엔 undefined의 값을 갖고있다가 resolve가 호출이 되면 value로, reject가 호출이 되면 error 로 변경
  • 한 번 변경된 상태는 더 이상 변하지 않기 때문에, 처리가 끝난 프로미스 객체에 resolve 또는 reject를 호출하면, 무시됨

resolve, reject 사용하기

1. resolve

  • executor 함수에서 비동기 처리된 결과 값을 반환할 때에는, 매개변수로 받은 resolve 콜백함수에 결과값을 전달
  • reslove 콜백함수에 전달된 값은 프로미스 객체의 then 메서드를 이용해 사용할 수 있고, then 메서드에는 executor 함수에서 전달한 값이 매개변수로 전달
  1. 프로미스 객체의 생성 + executor함수 실행
  2. executor함수에서는 매개변수로 받은 콜백함수 중 resolve함수를 사용해 "성공"을 전달
  3. 프로미스 객체의 state는 pending -> fulfilled / result는 undefined -> 성공으로 변경
  4. then 메서드를 통해 프로미스 객체의 result 값을 매개변수로 받아 콘솔에 출력

2. reject

  • 비동기 처리에 실패할 경우

  • reject함수가 실행

  • 프로미스 객체의 state는 pending -> rejected / result는 undefined -> "실패" 로 변경

  • 콘솔창에 아무것도 출력되지 않음

  • reject 함수를 사용해, 작업이 실패했을 때 결괏값을 사용하기 위해서는 catch 메서드를 사용

콜백지옥을 해결하는 Promise 객체

const workA = (value) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(value + 5);
    }, 5000);
  });
  return promise;
};

const workB = (value) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(value - 3);
    }, 3000);
  });
  return promise;
};

const workC = (value) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(value + 10);
    }, 10000);
  });
  return promise;
};

workA(10).then((resA) => {
  console.log(`1. ${resA}`);
  workB(resA)
    .then((resB) => {
      console.log(`2. ${resB}`);
      workC(resB).then((resC) => {
        console.log(`3. ${resC}`);
      });
    })
    .catch((error) => {
      console.log(error);
    });
});

조금 더 깔끔하게 정리해보자.

프로미스 체이닝 !

계속해서 프로미스 객체를 반환하며, then 메서드를 연속으로 사용하는 것

const workA = (value) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(value + 5);
    }, 5000);
  });
  return promise;
};

const workB = (value) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(value - 3);
    }, 3000);
  });
  return promise;
};

const workC = (value) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(value + 10);
    }, 10000);
  });
  return promise;
};

workA(10)
  .then((resA) => {
    console.log(`1. ${resA}`);
    return workB(resA);
  })
  .then((resB) => {
    console.log(`2. ${resB}`);
    return workC(resB);
  })
  .then((resC) => {
    console.log(`3. ${resC}`);
  })
  .catch((error) => {
    console.log(error);
  });
profile
`나는 ${job} 개발자`

1개의 댓글

comment-user-thumbnail
2023년 7월 2일

https://melonplaymods.com/2023/06/11/tank-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/metal-gear-rising-revengeancethe_foxan_mp-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/green-arm-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/apeirophobia-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/fighter-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/cameraken_kaneki-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/cactus-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/pacific-rim-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/stick-figure-fight-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/survival-kit-v-0-4-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/engineering-and-technical-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/slap-battles-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/one-night-at-flumptys-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/infected-melon-infected-watermelon-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/tank-carro-armato-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/technologist-mod-for-melon-playground/
https://melonplaymods.com/2023/06/10/bumblebee-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/ultraman-tiga-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/pack-for-many-items-from-minecraft-beta-2-mod-for-melon-playground/
https://melonplaymods.com/2023/06/11/small-prestigious-house-mod-for-melon-playground/

답글 달기