모던 자바스크립트 Deep Dive - 46. 제너레이터와 async / await

지영·2022년 2월 23일
0

JavaScript

목록 보기
36/37
post-thumbnail

async / await


46.6 async / await

async / await는 프로미스를 기반으로 동작한다.

async / await 를 사용하면
프로미스의 then/ catch/ finally 후속 처리 메서드에 콜백 함수를 전달해서 비동기 처리 결과를 후속 처리할 필요 없이
--> 마치 동기 처리처럼 프로미스를 사용할 수 있다!

다시 말해, 프로미스의 후속 처리 메서드 없이
--> 마치 동기 처리처럼 프로미스가 처리 결과를 반환하도록 구현할 수 있다.


46.6.1 async 함수

await 키워드는 반드시 async 함수 내부에서 사용해야 한다.

async 함수는 async 키워드를 사용해 정의하며 언제나 프로미스를 반환한다.

async함수가 명시적으로 프로미스를 반환하지 않더라도
--> async 함수는 암묵적으로 반환값을 resolve 하는 프로미스를 반환한다.

// async 함수 선언문
async function foo(n) {
  return n;
}

foo(1).then((v) => console.log(v));

//  async 함수 표현식
const bar = async function (n) {
  return n;
};

bar(2).then((v) => console.log(v));

// async 화살표 함수
const baz = async (n) => n;

baz(3).then((v) => console.log(v));

// async 메서드
const obj = {
  async foo(n) {
    return n;
  }
};

obj.foo(4).then((v) => console.log(v));

// async 클래스 메서드
class Myclass {
  async bar(n) {
    return n;
  }
}

const myClass = new Myclass();
myClass.bar(5).then((v) => console.log(v));

클래스의 constructor 메서드는 async 메서드가 될 수 없다.

클래스의 constructor 메서드는 인스턴스를 반환해야 하지만,
--> async 함수는 언제나 프로미스를 반환해야 한다.


44.6.2 await 키워드

await 키워드프로미스가 settled상태(비동기 처리가 수행된 상태)가 될 때까지 대기하다가
--> settle 상태가 되면 프로미스가 resolve 한 처리 결과를 반환한다.

await 키워드는 반드시 프로미스 앞에서 사용해야 한다.

await 키워드는 다음 실행을 중지시켰다가
--> 프로미스가 settled 상태가 되면 다시 재개한다.


44.6.3 에러 처리

에러는 호출자 방향으로 전파된다.

즉, 콜 스택의 아래 방향(실행중인 실행 컨텍스트가 푸시되기 직전에 푸시된 실행 컨텍스트 방향)으로 전파된다.

하지만, 비동기 함수의 콜백 함수를 호출한 것은 비동기 함수가 아니기 때문에
--> try, catch문을 사용해 에러를 캐치할 수 없다.
(비동기 함수의 콜백 함수를 호출한 것은 아마도 이벤트 루프..?)
(호출하여 콜스텍에 실행 컨텍스트가 생성된(push) 후 평가와 실행은 아마 자바스크립트 엔진이..?)

async / await 에서 에러 처리는
--> try...catch 문을 사용할 수 있다.

콜백 함수를 인수로 전달받는 비동기 함수와는 달리,
--> 프로미스를 반환하는 비동기 함수는 명시적으로 호출할 수 있기 때문에
--> 호출자가 명확하다!

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

const foo = async () => {
  try {
    const wrongUrl = "https://wrong.url";

    const response = await fetch(wrongUrl);
    const data = await response.json;
    console.log(data);
  } catch (e) {
    console.error(e); // TypeError: Failed to fetch
  }
};
// foo 함수는 프로미스를 반환하는 비동기 함수인 
// async 함수로, 호출자가 명확하다!
foo(); 

위 예제의 foo 함수의 catch문은 HTTP통신에서 발생한 네트워크 에러뿐 아니라
--> try 코드 블록 내의 모든 문에서 발생한 일반적인 에러까지 모두 캐치할 수 있다!

async 함수 내에서 catch 문을 사용해서 에러 처리를 하지 않으면,
async 함수는 발생한 에러를 reject하는 프로미스를 반환한다.


따라서 async 함수를 호출하고 리턴된 프로미스 객체(발생한 에러를 reject하는)에
--> Promise.prototype.catch 후속 처리 메서드를 사용해 에러를 캐치할 수도 있다.

profile
천천히 운영되는 개발 블로그

0개의 댓글