JavaScript & React/JS 기초

자바스크립트 Promise 객체, async 및 await 개념 정리 예제

jimmy_AI 2024. 3. 24. 23:30
반응형

javascript에서 비동기 처리를 하는 과정에서 필수적인 개념인

Promise 객체, async 및 await의 개념들을

간단한 예시를 통하여 이해를 해보는 시간을 가져보도록 하겠습니다.

 

 

Promise 객체

Promise는 자바스크립트에서 비동기 작업을 표현하는 객체입니다.

 

비동기 작업이 완료된 후에 요청이 성공하면 결과값을 반환해주고,

실패한 경우에는 이유를 처리할 수 있는 방법을 제공하는 원리입니다.

 

해당 객체는 세 가지 상태를 가질 수 있는데요.

아직 요청을 처리하고 있는 중이라면 pending,

요청의 결과값을 성공적으로 받았다면 fulfilled,

요청이 실패하였다면 rejected의 상태를 가지게 됩니다.

 

Promise 객체의 선언 방식은 다음과 같이 정리할 수 있습니다.

const promise = new Promise((resolve, reject) => {
  // 비동기 작업 수행
  if (/* 작업 성공 */) {
    resolve(value);
  } else {
    reject(error);
  }
});

 

resolve 및 reject의 두 가지 인자를 input으로 받으며,

작업 성공 시에는 resolve로 원하는 값을 반환하며 fulfilled 상태로 만들고,

실패 시에는 reject로 에러 메시지를 알려주며 rejected 상태로 만드는 것입니다.

 

예를 들어, delay라는 시간 만큼 기다리는 Promise 객체를 함수로 만든 예시는 다음과 같습니다.

delay가 숫자가 아니거나 음수인 경우에는 reject를 진행하는 예시입니다.

function timeoutPromise(delay) {
  return new Promise((resolve, reject) => {
    if (typeof delay !== 'number' || delay < 0) {
      reject(new Error("Delay cannot be negative"));
    } else {
      setTimeout(() => {
        resolve(`Completed after ${delay} ms`);
      }, delay);
    }
  });
}

 

 

Promise의 사용 방법: then - catch

Promise는 then - catch 구문과 같이 사용하여,

성공이나 실패 시에 사용할 함수를 같이 지정할 수 있습니다.

 

예를 들어, 위에서 구현한 함수의 결과를 console에 출력하도록 하는 예시는

다음과 같습니다.

timeoutPromise(1000)
  .then(result => console.log(result)) // "Completed after 1000 ms" 출력
  .catch(error => console.error(error)); // 에러 처리

timeoutPromise(-1000)
  .then(result => console.log(result))
  .catch(error => console.error(error)); // "Delay cannot be negative" 출력

 

즉, then 내부의 함수는 성공 시에 실행되며,

catch 내부의 함수는 실패 시에 실행되는 것인데요.

 

여기서 then의 결과로 다른 Promise를 반환시켜

여러 번 중첩하여 연계하는 것도 가능합니다.

function firstTask() {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(1), 1000); // 첫 번째 작업이 1초 후에 1을 반환
    });
}

function secondTask(resultFromFirst) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(resultFromFirst + 2), 1000); // 두 번째 작업이 첫 번째 결과에 2를 더해 반환
    });
}

function thirdTask(resultFromSecond) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(resultFromSecond * 3), 1000); // 세 번째 작업이 두 번째 결과를 3배로 반환
    });
}

firstTask()
    .then(result => {
        console.log('First task result:', result);
        return secondTask(result); // 첫 번째 작업의 결과를 두 번째 작업에 전달
    })
    .then(result => {
        console.log('Second task result:', result);
        return thirdTask(result); // 두 번째 작업의 결과를 세 번째 작업에 전달
    })
    .then(result => {
        console.log('Final result:', result); // 최종 결과 출력
    })
    .catch(error => {
        console.error('An error occurred:', error); // 오류 처리
    });

 

예를 들어, 위의 예시에서는 총 3초가 소요되고,

최종 결과 값은 1 -> 3 -> 9로 9가 되는 것을 이해해볼 수 있습니다.

 

이 경우에도 오류 처리를 위한 catch는 마지막에 1번만 수행해주어도 됩니다.

 

 

async 및 await

async 및 await 구문은 위의 Promise 객체를 일반적인 동기 함수처럼

높은 가독성으로 쉽게 사용할 수 있도록 도입된 구문입니다.

 

위의 예제에서 구현했던 timeoutPromise 함수를 

then - catch 구문 대신 async 함수를 사용하면 다음과 같이 사용이 가능해집니다.

async function runTimeoutAsync(time) {
  try {
    const result = await timeoutPromise(time);
    console.log(result); // 성공 시 결과 출력
  } catch (error) {
    console.error(error); // 실패 시 에러 처리
  }
}

runTimeoutAsync(1000); // "Completed after 1000 ms" 출력
runTimeoutAsync(-1000); // "Delay cannot be negative" 에러

 

즉, async 함수로 전체 과정이 비동기로 진행되는 것을 선언하게 되는 것이며,

await는 Promise의 결과를 기다리면서 다음 코드들이 실행될 수 있게 돕는 역할을 합니다.