비동기, CallBack 함수와 Promise, async

e-pong:)·2022년 11월 23일
0

비동기 작업의 문제 해결

특정 로직의 실행이 끝날때 까지 기다리지 않고, 나머지 코드를 먼저 실행하는 비동기 처리는 서버에게 데이터를 요청했을 때, 서버에서의 응답 데이터를 언제 받을지 모른다.

또한, 비동기 작업을 통해 여러 로직을 동시에 처리 할 때, 작업들이 정상적으로 끝났는지, 어떤 작업이 우선적으로 끝나게 되는지 확인할 필요가 있다.

비동기 작업이 필요한 경우

  • 브라우저에서는 ajax라 불리는 XMLHttpRequest 객체를 활용하여 비동기적으로 요청을 보내고 받을 수 있다.
  • Fetch API를 사용
  • 파일을 다룰 때 쓰는 함수

Call Back 함수

function taskA(a) {
  setTimeout(() => {
    const res = a * -1;
    return res;
  }, 2000);
}

const res = taskA(2);
console.log(res);

위 코드에서, 동기적 처리라면 출력값이 -2가 출력되어야 하지만, setTimeOut은 비동기 처리이기 때문에 setTimeOut을 통해 데이터를 받기 전에 console.log(res)가 실행되어 undefined가 출력된다.

따라서, 비동기로 실행하여 받은 데이터 결과 값을 가지고 처리를 해야할 필요가 있다.
이때, callback 함수를 이용한다.

function taskB(a, cb) {
  setTimeout(() => {
    const res = a * -1;
    cb(res);
  }, 2000);
}

taskB(2, (res) => {
  console.log(res);
});

비동기 처리를 포함한 함수를 호출할 때 매개변수로 callback 함수를 전달해주고, 비동기로 실행하여 받은 데이터 결과 값을 callback 함수의 매개변수로 전달하여 처리해준다.

Promise란?

promise는 비동기 처리를 위해 사용되는 하나의 객체이다.
콜백함수를 사용하여 비동기 작업을 처리할 때 콜백 지옥으로 인한 단점을 보완할 수 있다.

Promise 생성

Promisesms ES6에서 새롭게 도입한 객체이므로, 생성자를 통해 인스턴스화 한다.

// Promise 객체의 생성
const promise = new Promise((resolve, reject) => {	//pending(대기) 상태
  // 비동기 작업을 수행한다.

  if (/* 비동기 작업 수행 성공 */) {
    resolve('result');	//fulfilled(이행) 상태
  }
  else { /* 비동기 작업 수행 실패 */
    reject('failure reason');	//rejected(실패) 상태
  }
});

Promise 상태(states)


pending : 비동기 처리 로직이 아직 완료되지 않은 상태
Fulfilled : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
Rejected : 비동기 처리 실패하거나 오류가 발생한 경우

Promise 객체

function isPositiveP(number) {
  const executor = (resolve, reject) => {
    setTimeout(() => {
      if (typeof number === "number") {
        //성공 -> resolve
        console.log(number);
        resolve(number >= 0 ? "양수" : "음수");
      } else {
        //실패 -> reject
        reject("주어진 값이 숫자형 값이 아닙니다.");
      }
    }, 2000);
  };

  return new Promise(executor);
}

isPositiveP(10)
  .then((res) => {
    console.log("작업 성공 : ", res);
  })
  .catch((err) => {
    console.log("작업 실패 : ", err);
  });

Promise 요약정리

  • Promise는 비동기 작업을 생성/시작하는 부분(new Promise(...))과 작업 이후의 동작 지정 부분(then, catch)을 분리함으로써 기존의 러프한 비동기 작업보다 유연한 설계를 가능토록 한다.

  • Promise를 만드는 순간 비동기 작업이 시작되며, 비동기 작업을 성공으로 간주하고 싶을 경우 resolve를 호출하고, 실패로 간주하고 싶다면 reject 함수를 호출한다.

  • 비동기 작업이 성공했을 때의 후속 조치를 지정하고 싶다면 then으로, 실패 시의 후속 조치는 catch로 지정해주면 된다.

async

//Promise function
function getUser() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("espania");
    }, 1000);
  });
}

getUser().then((res) => {
  const user = res;
  console.log("user : ", user);	//espania 출력
});

Promise를 이용하여 비동기 작업을 처리 할 수 있지만 조금 더 간편하게 비동기 작업을 처리할 수 있는 방법이 async 키워드를 이용하는 것이다.

	//async
	function delay(ms){
      	return new Promise((resolve)=>{
          	setTimeOut(resolve,ms);
        })
    }

	async function getUser(){
      delay();
      return "espania"
    }

	getUser().then((res)=>{
      const user = res;
      console.log("user : ", user); //espania 출력
    })

위와 같이 함수 앞에 async 키워드를 붙이게 되면, 해당 함수는 Promise 객체를 반환한다.

await

await 키워드는 async 키워드를 가진 함수 내부에서만 사용할 수 있다.
비동기 처리 함수에 await 키워드를 붙이게 되면 동기적으로 수행한다.

	//await
    function delay(ms) {
      return new Promise((resolve) => {
        setTimeout(resolve, ms);
      });
    }

    async function getApple() {
      await delay(3000);	//3초 기다리고 실행
      return "apple";
    }

다음과 같이 비동기 함수를 처리하는 delay 함수 앞에 await을 붙이게 되면 해당 함수를 동기적으로 처리한다.

Promise를 async로 변경하기

getApple과 getBanana라는 함수가 있을 때,

	async function getApple() {
    await delay(3000);
    return "apple";
  }

  async function getBanana() {
    await delay(3000);
    return "banana";
  }

Promise 객체를 다음가 같이 중첩적으로 체이닝하게 되면 코드가 복잡해지고 가독성이 떨어진다.

  function pickFruits() {
   	 return getApple().then((apple)=>{
       	return getBanana().then((banana)=>{
          return `${apple} + ${banana}`;
        })
     })
  }

  pickFruits().then(console.log);

따라서 async를 사용하면 로직을 좀 더 간단하게 만들 수 있다.

  async function pickFruits() {
    const apple = await getApple();
    const banana = await getBanana();

    return `${apple} + ${banana}`;
  }

  pickFruits().then(console.log);

Async와 Promise 요약 정리

  • Promise는 JavaScript에서 비동기 처리에 사용되는 객체이며 resolve와 reject를 통해 성공/실패 케이스를 작성할 수 있다.
    -await은 Promise 기반으로 등장한다. 비동기 코드를 async,await을 통해 가독성을 높여주며 예외 처리는 try-catch을 통해 수행할 수 있다.
  • DB로부터 데이터를 가져와야하는데 사용자에게는 지속적으로 서비스를 제공해야 할 경우 특정 메서드를 비동기로 가져와야 하기 때문에 이럴 때 async-await 구문을 사용할 수 있다고 보면 된다.
profile
말에 힘이 있는 사람이 되기 위해 하루하루, 성장합니다.

0개의 댓글