46.6 async/await

Sooo·2023년 10월 18일
0

(880~885)

요약

  • 제너레이터의 단점: 코드가 장황해지고 가독성이 나빠졌다

  • ES8에서 더 간단하고 가독성 좋게 비동기처리를 할 수 있는 async/await 도입

  • async/await도 프로미스를 기반으로 동작하지만, 후속처리 메서드(then/catch/finally)필요 없이 동기 처리처럼 프로미스 결과를 반환할 수 있다.

async

  • async 함수는 항상 프로미스를 반환한다. ⇒ 클래스의 constructor는 인스턴스를 반환해야하므로 async함수가 될 수 없다.
  • 내부에서 명시적으로 반환하지 않더라도, 암묵적으로 반환값을 resolve하는 프로미스를 반환한다

await

  • 프로미스가 settled(비동기 처리 완료)상태가 될 때까지 대기하다가, settled 상태가 되면 resolve한 처리 결과를 반환한다.
  • 반드시 프로미스 앞에서 사용해야 한다.

async함수 안에서 await를 사용하면 settled상태가 될 때까지 대기하므로, 연달아 각각의 await를 사용하면 앞에서 작성한 await가 완료되기 전까지 다음의 await를 실행할 수 없다. 따라서 await가 순차적으로 완료될 필요가 없는 상황에서는 Promise.all()로 묶어서 처리하는 게 좋다

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));
}

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))
	]);
}

foo(); //약 3초 소요

반대로 앞선 비동기 처리의 결과를 가지고 다음 비동기 처리를 수행해야하는 경우, 비동기 처리의 순서가 보장되어야 하므로 모든 프로미스에 await를 붙여서 순차적으로 처리해야 한다.

예외처리

  • “에러는 호출자 방향으로 전파된다”: “콜스택의 아래 방향으로 전파된다”
  • 비동기 함수의 콜백 함수를 호출한 것은 비동기 함수가 아니기 때문에 try…catch문을 사용해 에러를 캐치할 수 없다
    try {
    	setTimeout(() => { throw new Error('Error'); }, 1000);
    } catch (e) {
    	// 에러를 캐치하지 못함
    	console.error('캐치한 에러', e);
    }
  • 콜백함수를 인수로 전달받는 비동기함수와 달리, 프로미스를 반환하는 비동기 함수는 명시적으로 호출할 수 있으므로 호출자가 명확하다. 따라서 try…catch로 에러를 캐치할 수 있다.
  • async함수 안에서 catch를 사용해서 에러처리를 하지 않으면, 발생한 에러를 reject하는 프로미스를 반환한다 ⇒ async함수를 호출하고 catch를 사용할 수도 있다.

느낀 점

  • Promise.all() => 잘 써보지 않았는데 기억하자
  • 47장 에러처리가 궁금

0개의 댓글