티스토리 뷰

11.8 Async/await

Async functions

functions 앞에 async를 붙이면 항상 프라미스를 반환한다. 프라미스가 아닌 값이 반환되더라도, 이행 상태의 프라미스로 값을 감싸서 이행된 프라미스가 반환되도록 한다.

async function f() {
  return 1;
}

f().then(alert); // 1

Await

await는 async 함수 안에서만 동작한다. 프라미스가 처리될 때까지 함수 실행을 기다리고, 프라미스가 모두 수행되면 결과를 반환한다.

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("완료!"), 1000)
  });

  let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)

  alert(result); // "완료!"
}

f();

또 다른 예시

async function showAvatar() {

  // JSON 읽기
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();

  // github 사용자 정보 읽기
  let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
  let githubUser = await githubResponse.json();

  // 아바타 보여주기
  let img = document.createElement('img');
  img.src = githubUser.avatar_url;
  img.className = "promise-avatar-example";
  document.body.append(img);

  // 3초 대기
  await new Promise((resolve, reject) => setTimeout(resolve, 3000));

  img.remove();

  return githubUser;
}

showAvatar();

참고로 await는 최상위 레벨 코드에서 사용이 안된다.(async로 감쌀 함수가 없어서 당연한 것 같기도...) 다만, 익명 함수로 감싸면 사용 가능하다.

(async () => {
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();
  ...
})();

thenable 객체도 가능하다.

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve);
    // 1000밀리초 후에 이행됨(result는 this.num*2)
    setTimeout(() => resolve(this.num * 2), 1000); // (*)
  }
};

async function f() {
  // 1초 후, 변수 result는 2가 됨
  let result = await new Thenable(1);
  alert(result);
}

f();

 

Error handling

프라미스가 거부되면 마치 throw문을 작성한 것처럼 에러가 던져진다. 

async function f() {
  await Promise.reject(new Error("에러 발생!"));
}

// ---------
// 위 코드와 동일한 동작을 한다. 
async function f() {
  throw new Error("에러 발생!");
}

await가 던진 에러도 try...catch를 사용해 잡을 수 있다.

async function f() {

  try {
    let response = await fetch('http://유효하지-않은-주소');
    let user = await response.json();
  } catch(err) {
    // fetch와 response.json에서 발행한 에러 모두를 여기서 잡습니다.
    alert(err);
  }
}

f();

Promise.all과도 함께 사용 가능하다.

// 프라미스 처리 결과가 담긴 배열을 기다립니다.
let results = await Promise.all([
  fetch(url1),
  fetch(url2),
  ...
]);
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday