Javascript - 비동기 코드 (with Promise)

lwoody·2020년 12월 20일
0

Javascript

목록 보기
4/4
post-thumbnail

비동기 코드에 대한 간단한 그림 설명

기본적으로 자바스크립트 엔진(V8, Spider Monkey 등)은 싱글 스레드
👉 Only one action at a time

하지만 브라우저 or nodejs 환경에서 event loop, callback queue 등을 이용해 보조해 단순한 싱글 스레드 원리와는 다르게 동작함

참고 : 자바스크립트 동작 원리 및 구조
특정 실행에 대한 정보를 기억하고 시점에 맞게 실행시켜줌

Promises

  • 비동기에 활용 가능한 operation chain
    • 굳이 비동기 코드에만 사용 안해도 됨
fetch('https://foo.com/resource/1', {})
     .then(response => response.json())
     .then(jsonData => console.log(jsonData));
  • Promise : 특정 값이나 에러를 반환하는 함수 정보를 포함하는 자바스크립트 객체 (굳이 비동기 함수x)
  • 콜백 hell을 해결하는데 사용하기 위해 개발함
const myPromise = new Promise(function(resolve, reject) {
   setTimeout(function () {
      resolve('it worked');
   },2000)
});

myPromise
   .then(successString => {
      console.log(successString); // it worked
      return '123'; // 일반적인 데이터 return 가능
   })
   .then(data => {
      console.log(data); // 123
      return myPromise; // promise를 리턴하면 기존 promise를 대체함
   })
   .then(data => {
      console.log(data); // it worked
   });
  • then 에 할당하는 함수가 relove 에 할당됨
  • then 은 항상 새로운 unsettled 상태의 Promise 를 반환함
    • 체이닝이 가능해짐
  • 위의 2번째 케이스에서 myPromise는 이미 resloved된 상태이므로 기존 resolved된 응답값을 사용함
    • promise는 오직 한번만 resolved

states

Pending : 아직 응답을 받지 못한 promise 내의 초기 상태, 코드
Setteled

  • Fulfilled : resolved된 promise (성공적으로 수행된 상태)
  • Rejected : rejected된 promise

Promisifying APIs

아래처럼 custom 화 시킬 수 있음

const setTimer = (duration) => {
   return new Promise(function(resolve, reject) {
      setTimeout(function () {
         resolve('it worked);
      },duration)
   });
};

setTimer(2000)
   .then(successString => {
      console.log(successString); // it worked
      return '123'; // 일반적인 데이터 return 가능
   })
   .then(data => {
      console.log(data); // 123
      return setTimer(3000); // promise를 리턴하면 기존 promise를 대체함
   })
   .then(data => {
      console.log(data); // it worked
   });

error 핸들링

rejected state를 가지는 promise

fetch('https://foo.com/resource/1', {})
     .then(
     	response => response.json(),
        error => return 'Error handled'
     )
     .then(
     	response => console.log(response),
     	error => console.log(error)
     );
  • fallback 함수 코드를 then의 두번째 인자로 넣어줌

  • promise 의 에러 발생시에 가장 처음에 구현된 error fallback 코드가 실행되고, 그 fallback 코드 이전의 then 체이닝들은 무시됨.
    그 이후의 체이닝들은 이전의 체이닝이 resolved되었다고 판단하고, 제공하는 응답값을 사용해 resolve 시도하게 됨.

    • 위처럼 에러 코드에서 일반 데이터 (스트링) 응답 : 스트링 데이터가 정상적으로 반환하므로 두번째 then에서는 error로 가지 않음
    • 에러에 응답값 없는 경우 (기존 promise를 그대로 받음) : 두번째 then에서는 error로 가지 않고, resolve 에 할당한 함수에서undefined 찍음

catch 메소드 사용한 방법

fetch('https://foo.com/resource/1', {})
     .then(
     	response => response.json()
     )
     .catch(
     	error => console.log(error) // error 발생시 실행됨
     )
     .then(
     	response => console.log(data); // undefined
     );
  • catch도 위에서 설명한 규칙대로 선언한 순서에 따라 동작하게 됨

async, await

  • 조금 더 편리하게 사용하기 위한 synthetic sugar
  • 함수 내에서만 가능함
  • async prefix 붙은 함수는 항상 promise를 반환함 (return 명시가 없더라도)
  • await prefix는 async 함수 내에만 사용 가능함
// async function foo() {...}
const sendRequest = async () => {
  try{
    const response = await fetch('https://foo.com/resource/1', {});
    console.log('got reponse!');
    console.log(reponse);
  
    const data = reponse.json();
    console.log(data);
  } catch (err) {
    console.log('got error');
  }
};

Promise 메소드

참고 : MDN > Promise 프로토타입에서 제공하는 메소드들

Promise.all()

  • promise를 원소로 가지는 배열을 인자로 받음
  • 여러개의 promise를 같이 execute시키고 모든 promise로 된 응답을 배열로 만들어 반환함
  • 주어진 promise 중 하나가 거부하는 경우, 첫 번째로 거절한 promise의 이유를 사용해 모두 거부됨
Promise.all([getPosition(), setTimer(1000)]) // [promise1, promise2]
  .then(promiseData=>console.log(promiseData)); 

Promise.allSettled()

  • all 사용성에서 각각의 이행하거나 거부했을 때에 대한 대응을 할 수 있는 Promise 객체를 얻고 싶을때 사용함
Promise.allSettled([getPosition(), setTimer(1000)]) // [fullfilledPromise1, rejectedPromise2]
  then((results) => results.forEach((result) => console.log(result)));

Promise.race()

  • promise를 원소로 가지는 배열을 인자로 받음
  • 여러개의 promise를 같이 execute시킨 후 가장 먼저 받은 응답을 사용함 (이행된 promise or 거절된 promise 둘 다 해당 됨)
  • 늦은 응답은 요청은 이미한것이고 응답이 무시만 될 뿐임
Promise.race([getPosition(), setTimer(1000)]) // promise1
  .then(data=>console.log(data)); 

throw, reject 비교

간단 요약 설명

profile
Web Service Developer

0개의 댓글