async와 await
비동기 코드를 위에서 아래로 읽히게 작성합니다.
위에서 아래로 읽히게 씁니다
앞 단원의 then 체인은 콜백보다 낫지만, 여전히 값을
함수 안에서만 쓸 수 있습니다. await 는 그것을
변수에 바로 담게 해 줍니다.
// then 으로 loadUser().then(user => { console.log(user.name); }); // await 로 const user = await loadUser(); console.log(user.name);
규칙은 둘입니다. await 는 Promise 앞에 붙입니다.
그리고 await 를 쓰는 함수에는
async 를 붙입니다.
차례대로 기다리기
function delay(ms, value) { return new Promise(resolve => setTimeout(() => resolve(value), ms)); } async function run() { console.log("시작"); const first = await delay(100, "첫째"); console.log(first); const second = await delay(100, "둘째"); console.log(second); return "끝"; } const result = await run(); console.log(result);
5.2 의 콜백 지옥과 견주어 보세요. 중첩이 사라지고 보통의 코드처럼 읽힙니다.
마지막 두 줄처럼 함수 밖에서도 await 를 쓸 수
있습니다. 이것을 최상위 await 라고 합니다.
async 함수는 Promise 를 돌려줍니다
async function greet() { return "안녕"; } console.log(greet()); console.log(await greet()); greet().then(value => console.log("then 으로도:", value));
async 를 붙이면 무엇을 돌려주든 Promise 로
감싸집니다. 그래서 then 으로도 받을 수 있고,
부르는 쪽에서 await 로도 받을 수 있습니다.
실패는 try...catch 로
catch 를 이어 붙이는 대신, 보통의 코드에서 쓰던
try...catch 를 그대로 사용합니다.
async function mayFail(shouldFail) { if (shouldFail) { throw new Error("문제가 생겼습니다"); } return "성공"; } try { console.log(await mayFail(false)); console.log(await mayFail(true)); console.log("이 줄은 나오지 않습니다"); } catch (error) { console.log("잡았습니다:", error.message); } finally { console.log("끝났습니다"); }
throw 를 만나면 try 의
남은 줄을 건너뛰고 catch 로 갑니다. 5.3 의 체인이
중간 then 을 건너뛴 것과 같습니다.
기다리지 않아도 되는 것은 함께
await 를 줄줄이 적으면 차례로 기다립니다.
서로 상관없는 일이라면 함께 시작해야 빠릅니다.
function delay(ms, value) { return new Promise(resolve => setTimeout(() => resolve(value), ms)); } const start = Date.now(); // 차례로 기다립니다 — 400밀리초 const a = await delay(200, "가"); const b = await delay(200, "나"); console.log(a, b, Date.now() - start >= 400); const start2 = Date.now(); // 함께 기다립니다 — 200밀리초 const [c, d] = await Promise.all([delay(200, "다"), delay(200, "라")]); console.log(c, d, Date.now() - start2 < 400);
Promise.all 의 결과를 3.7 의 구조 분해로 바로
나눠 받았습니다.
처음에 자주 걸리는 것
값 대신 Promise 가 담깁니다. 오류가 나지 않아
undefined 가 나올 때까지 모릅니다.
const user = loadUser(); // Promise 가 담깁니다 console.log(user.name); // undefined const user = await loadUser(); // 이렇게 적습니다
함수 안에서 await 를 쓰려면 그 함수에
async 가 있어야 합니다.
SyntaxError: await is only valid in async functions
서로 상관없는 요청을 for 안에서 하나씩 기다리면
개수만큼 시간이 곱해집니다. Promise.all 로 함께
시작하세요.
직접 해보기
아래 코드를 await 로 바꿔 보세요.
숫자 셋을 차례로 처리하되, 하나가 실패해도 나머지를 계속 처리하세요. 음수면 실패합니다.
try...catch 를 두면 그 회차만 걸러집니다.이 단원의 정리
await는 Promise 의 값을 변수에 바로 담습니다.await를 쓰는 함수에는async를 붙입니다.async함수는 무엇을 돌려주든 Promise 로 감쌉니다.- 실패는
try...catch로 받습니다. - 서로 상관없는 일은
Promise.all로 함께 시작합니다.