async, await 사용 방법

wonway·2024년 2월 19일
0
post-thumbnail

요약

fetch() 함수 예시

  • fetch()를 감싸는 외부 함수에 async를 붙인다.
  • async가 붙으면 함수는 promise를 return
  • fetch() 함수 앞에 await을 붙이면 fetch()의 promise 결과를 기다리며 함수는 일시 정지
  • response.json() 앞에 await을 붙여서 json 파싱하는 동안 일시 정지
  • 순차적으로 한 줄씩 진행되므로 동기 코드와 비슷한 형태가 되었다.
  • await은 async함수 내에서만 사용 가능
  • 오류 처리 : try-catch 구문 사용
async function 외부함수() {
  try {
    const response = await fetch('https://example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('An error occurred:', error);
  }
}

기본 개념

async-await은 비동기 처리를 위한 패턴이다. Callback과 Promise의 단점을 보완하고 가독성 좋게 코드를 작성할 수 있다.

Callback의 단점

콜백 지옥 : 콜백 중첩 시 발생한다.

에러 처리의 어려움 : 에러 처리 로직을 따로 구현해야 하는 번거로움이 있다.

Promise의 단점

에러를 놓치는 경우 : then() 체인을 연결하다가 마지막에 catch() 메서드를 누락하는 경우

복잡한 비동기 제어 : 여러 비동기 작업을 순차적으로 실행한 다음 그 결과를 모아서 처리해야하는 경우

예제

복잡한 비동기 제어의 경우를 예시로 promise와 async-await 비교

function fetchData() {
  return fetch('https://example.com/data').then((response) => response.json());
}

function fetchMoreData(dataId) {
  return fetch(`https://example.com/more-data/${dataId}`).then((response) => response.json());
}

// 여러 비동기 작업을 순차적으로 실행
fetchData()
  .then((data) => {
    console.log(data);
    // 첫 번째 비동기 작업의 결과를 사용하여 두 번째 비동기 작업을 실행
    return fetchMoreData(data.id);
  })
  .then((moreData) => {
    console.log(moreData);
    // 추가 로직...
  })
  .catch((error) => {
    console.error('An error occurred:', error);
  });

async

함수의 앞에 붙여서 사용한다.

해당 함수는 promise를 return한다.

await

async 내부에서만 사용 가능하다.

await이 붙은 비동기 함수가 완료되기까지 실행이 일시 중지된다.

async function fetchData() {
  const response = await fetch('https://example.com/data');
  return response.json();
}

async function fetchMoreData(dataId) {
  const response = await fetch(`https://example.com/more-data/${dataId}`);
  return response.json();
}

async function executeAsyncTasks() {
  try {
    const data = await fetchData();
    console.log(data);
    // 첫 번째 비동기 작업의 결과를 사용하여 두 번째 비동기 작업을 실행
    const moreData = await fetchMoreData(data.id);
    console.log(moreData);
    // 추가 로직...
  } catch (error) {
    console.error('An error occurred:', error);
  }
}

executeAsyncTasks();

동기 코드처럼 비동기 함수를 실행하고 기다렸다가 promise를 할당하여 사용한다.

오류 처리하기

callback

function fetchData(callback) {
  // 데이터를 가져오는 시뮬레이션
  const error = null; // 에러가 없다고 가정
  const data = "Some data"; // 가져올 데이터

  if (error) {
    callback(error, null); // 에러가 있다면, 첫 번째 매개변수로 에러 전달
  } else {
    callback(null, data); // 에러가 없다면, 첫 번째 매개변수로 null, 두 번째 매개변수로 데이터 전달
  }
}

// fetchData 함수 사용
fetchData((error, data) => {
  if (error) {
    console.error("An error occurred:", error); // 에러 처리
  } else {
    console.log("Received data:", data); // 정상적으로 데이터를 받아 처리
  }
});

promise

위의 예제 중

catch (error) {
    console.error('An error occurred:', error);
  }

then() 메서드가 연속된 체인의 경우는 마지막에서 catch()를 작성하여 감지한다.

then() 메서드가 독립적으로 사용되는 경우 각각 catch() 작성해서 에러를 처리해야 한다.

이 두 가지 방식이 헷갈려서 실수가 발생할 가능성이 있다.

async-await

위의 예제 중

async function executeAsyncTasks() {
  try {
    const data = await fetchData();
    console.log(data);
    // 첫 번째 비동기 작업의 결과를 사용하여 두 번째 비동기 작업을 실행
    const moreData = await fetchMoreData(data.id);
    console.log(moreData);
    // 추가 로직...
  } catch (error) {
    console.error('An error occurred:', error);
  }
}

try 안에 로직을 작성하고 try 뒤에 catch를 통해 에러를 try 안에서 발생한 에러를 통합적으로 잡을 수 있다.

profile
문제를 컴퓨터로 해결하는 데서 즐거움을 찾는 프론트엔드 개발자

0개의 댓글