async/await와 에러 처리 알아보기 [모던 자바스크립트 Deep Dive : 45장, 46장]

조성원·2023년 5월 31일
0

async/await

기존 자바스크립트에서는 비동기 처리를 위해 제너레이터를 사용했지만,
보다 간단한 방식으로 async/await가 등장했습니다.

async/await는 프로미스를 기반으로 동작합니다.
프로미스의 then/catch/finally 후속 처리 메서드에 콜백 함수를 전달해서
비동기 처리 결과를 후속 처리할 필요 없이
마치 동기 처리처럼 사용할 수 있습니다.

const fetch = require('node-fetch');

async function fetchTodo() {
  const url = 'https://`
  
  const response = await fetch(url);
  const todo = await response.json();
  console.log(todo); //{user: 1, id: 1, title: '~', completed: false}
  
fetchTodo();

async 함수

await 키워드는 반드시 async 함수 내부에서 사용해야 합니다.
async 함수는 언제나 프로미스를 반환합니다.

await 키워드

await 키워드는 프로미스가 settled 상태가 될 때까지 대기하다가
상태가 되면 프로미스가 resolve한 처리 결과를 반환합니다.

const fetch = require('node-fetch');

async getGithubUserName = async id => {
  const res = await fetch('https://~/${id}`);
  const { name } = await res.json();
  console.log(name); // Lee
};
  
getGithubUserName();

프로미스 상태

  • pending: 비동기 처리가 아직 수행 x
  • fulfilled: 비동기 처리가 수행된 상태(성공), resolve 함수 호출
  • reject: 비동기 처리가 수행된 상태(실패), reject 함수 호출

다만 모든 프로미스에 await 키워드를 사용하는 것은 주의해야 합니다.
await 키워드를 남발할 경우, 동기적으로 처리하는 것처럼 동작하기 때문에
더 많은 시간이 소요될 수 있습니다.

async function foo() {
  const a = await new Promise((resolve) => setTimeout(() => resolve(1), 3000));
  const b = await new Promise((resolve) => setTimeout(() => resolve(2), 2000));
  const c = await new Promise((resolve) => setTimeout(() => resolve(3), 1000));

  console.log([a, b, c]); // [1, 2, 3]
}

foo(); // 약 6초 소요된다.
async function foo() {
  const res = await Promise.all([
    new Promise((resolve) => setTimeout(() => resolve(1), 3000)),
    new Promise((resolve) => setTimeout(() => resolve(2), 2000)),
    new Promise((resolve) => setTimeout(() => resolve(3), 1000)),
  ]);

  console.log(res); // [1, 2, 3]
}

foo(); // 약 3초 소요된다.

Promise와 async/await의 차이점 한 줄 요약

① 에러 핸들링

  • Promise 를 활용할 시에는 .catch() 문을 통해 에러 핸들링을 해야 하지만,
  • async/await 은 try / catch를 통해 에러를 처리할 수 있습니다.

② 코드 가독성

  • Promise의 후속 처리 메서드인 .then() 의 hell의 가능성이 있습니다.
  • async/await 은 프로미스의 후속 처리 메서드 없이 마치 동기 처리처럼 프로미스가 처리 결과를 반환하도록 구현할 수 있기 때문에 코드 흐름을 이해 하기 쉽습니다.

async/await에서의 에러 처리

async/await에서의 에러 처리는 try, catch문을 통해 가능합니다.
만약 async 함수 내에서 catch 문을 사용해서 에러 처리를 하지 않으면,
에러를 reject하는 프로미스를 반환합니다.

const fetch = require('node-fetch');

async foo = async id => {
  try {
      const res = await fetch('https://~/${id}`); // 잘못된 url
  const data = await res.json();
  console.log(data);
} catch(err) {
  console.error(err); // TypeError: Failed to fetch
};
  
foo();

에러 처리

try, catch, finally 문

try {
// 실행할 코드
} catch (err) {
// try 코드에서 에러 발생시 실행
// err에는 try 코드 블록에서 발생한 Error 객체 전달
} finally {
// 에러 발생과 상관없이 반드시 한 번 더 실행
}

Error 객체

Error 생성자 함수는 에러 객체를 생성합니다.
Error 생성자 함수에는 에러를 상세히 설명하는 에러 메시지를 인수로 전달할 수 있습니다.

const error = new Error("invalid");
  • Error: 일반적 에러 객체
  • SyntaxError: 자바스크립트 문법에 맞지 않는 문을 해석할 때 발생하는 에러 객체
  • ReferenceError: 참조할 수 없는 식별자를 참조했을 때 발생하는 에러 객체
  • TypeError: 피연산자 또는 인수의 데이터 타입이 유효하지 않을 때 발생하는 에러 객체
  • RangeError: 숫자값의 허용 범위를 벗어낫을 때 발생하는 에러 객체
  • URIError: encodeURI 또는 decodeURI 함수에 부적절한 인수를 전달했을 때 발생하는 에러 객체
  • EvalError: eval 함수에서 발생하는 에러 객체

throw 문

에러를 발생시키려면 try 코드 블록에서 throw 문으로 에러 객체를 던져야 합니다

try {
  // 에러 객체를 던지면 catch 코드 블록이 실행되기 시작한다.
  throw new Error("something wrong");
} catch (error) {
  console.log(error);
}
profile
IT 트렌드에 관심이 많은 프론트엔드 개발자

0개의 댓글