promise, async/await

·2021년 8월 10일
0

javascript

목록 보기
7/13
post-thumbnail
백앤드 분야를 공부하기 시작했다.
당연히 시작은 nodeJS 부터📚📚

첫 백앤드 공부라 여러모로 걱정이 많았지만,
처음 언어를 접할 때 보다 저항?은 덜 한 편이다.
나중에 배울 라이브러리나 프레임웨크도 이정도 느낌이면 참 좋을텐데.

지금까지 배운 nodeJS 과정에서 가장 크게 기억나는 것은,
비동기가 정말 많이 사용된다는 것🧨🧨

서버를 호출하고🤙, 데이터를 구하고📀, 
원하는 값으로 재현하고🖼, 새로운 파일로 생성하는 등📁
서버 이면에서 꼭꼭 필요한 비동기식 이론.
다시금 훝어보고 가기!!🤔



PROMISE

콜백 함수가 발생하는 가장 큰 조건은, 부모 함수가 사용조건에 만족하여 콜백 함수에게 필요한 데이터 값을 나타내는 것이다.

순차적인 함수 사용이 1,2개 정도라면 비동기식을 어려워 할 사람이 없겠지만, 아이러니하게도 어떤 프로젝트를 하던 간에 함수를 5개, 6개 하물며 몇 십개를 순차적으로 호출해야하는 상황이 그리 드물지 않다.

/*
1.js, 2.js, 3.js 스크립트들이 있고 
순번에 맞추어 차례대로 실행이 이루어져야 한다.
param1은 error를 판단하고, 필요한 리턴 값은 param2로 맞춘다면
이렇게 쓰일 수 있다.
*/

function loadScript(param1, param2) {
...
}

loadScript('1.js', function(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', function(error, script) {
      if (error) {
        handleError(error);
      } else {
        // ...
        loadScript('3.js', function(error, script) {
          if (error) {
            handleError(error);
          } else {
            // 모든 스크립트가 로딩된 후, 실행 흐름이 이어집니다. (*)
          }
        });
      }
    })
  }
});

소위 콜백지옥 callback Hell 이라 불리는 피라미드 형태의 비동기 연속 코드는 만드는 개발자도, 참조하는 사람 역시 이해하기 복잡하다. 단순히 비동기식 3개여도 이정도인데 이러한 동작이 수십 번 교차해야하는 한다면 어떨까?

이런 점을 보완하고자 es6 에서 새롭게 추가 된 것이 바로 promise 구문 이다.

let promise = new Promise((resolve, reject) => {
 resolve();
 // if(!resolve) reject()
})

promise 는 두가지 인수를 받는다. 비동기식이 정상적으로 실행된다면 resolve를 호출한다. 하지만 어떠한 이유로 resolve가 실행되지 않는다면 두번째 인수인 reject를 호출한다.

state (대기) 상태의 경우 호출 이전에는 pending (보류) 정상적으로 식이 호출되면 fullfilled (이행)이 에러 시엔 rejected (거절)을 나타낸다.

then, catch, finally

Promise를 호출 이후 사용할 수 있는 메소드는 3가지 이다.

  • then : resolve()를 통한 리턴 값
  • catch : reject()를 통한 리턴 값
  • finally : 실행 여부와 상관없이 이후 이벤트 실행

Promise 의 가장 큰 장점은 코드의 가독성이 증가한다는 점이다. 또한 반복해서 재사용하는 예외처리 작업 역시 현저하게 줄어드는 편이다.throw 를 함께 사용한다면 각 작업마다 나타날 수 있는 error 상황도 쉽게 찾아낼 수 있어 에러 핸들링이 한결 편해진다.

// readFilePro(file) {
  ... 파일의 데이터를 불러온다.
  if(err)
  throw err
}

// writeFilePro(file, data) {
  ... 주어진 데이터를 통해 파일을 생성한다. 
}


readFilePro(`${__dirname}/dog.txt`)
  .then((data) => {
    return superagent.get(`https://dog.ceo/api/breed/${data}/images/random`);
  })
  .then((res) => {
    return writeFilePro('dog-img.txt', res.body.message);
  })
  .then(() => {
    console.log('Random dog image saved to file!');
  })
  .catch((err) => {
    console.log(err); 
    // throw err를 통해 err를 받아 콘솔에 나타낸다.
  })
  .finally(() => {
  	console.log(`Promise ended`)
  })



Async/Await

promise 를 사용할 줄 안다면 async/await 는 그리 이해하는데 어렵지 않다.
javascript 의 비동기 구문의 복잡성을 개선하기 위해 es8 에서 업데이트 된 promisesynthetic sugar 로서 함수에 async 만 붙이는 것으로promise 함수로 리턴한다. then 의 역할은 await 가 이어받는다.

(굳이 번거롭게 new 함수를 부르지 않아도 되는게 큰 장점)


// 위의 promise 식을 async/await로 변환한다면...

const getDogPic = async () => {
  try {
    const data = await readFilePro(`${__dirname}/dog.txt`);
    const imgUrl = await data((el) => el.body.message) 
    const text = await writeFilePro('dog-img.txt', imgUrl);
 
    console.log('Random dog image saved to file!');
    return text;
  } catch (err) {
    console.log(err);
    throw err;
  }
};
profile
새로운 것에 관심이 많고, 프로젝트 설계 및 최적화를 좋아합니다.

0개의 댓글