ES6에서 도입된 코드 블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수인 제너레이터를 사용해서 비동기 처리를 동기 처리처럼 동작하도록 했지만, ES8에 제너레이터보다 간단하고 가독성 좋게 동기 처리처럼 동작하도록 구현할 수 있는 async/await가 도입되었다.
async/await은 프로미스 기반으로 동작하고, 프로미스의 then/catch/finally 메서드 없이 동기 처리처럼 프로미스가 처리 결과를 반환하도록 구현할 수 있다. 즉 비동기 처리 결과를 후속 처리 메서드 없이 동기 처리처럼 프로미스가 처리 결과를 반환하도록 할 수 있다.
asyncasync 함수는 async 키워드를 사용해 정의하며, 언제나 프로미스를 반환한다.resolve하는 프로미스를 반환한다.// 함수 선언문
async fuction foo(n) { return n; }
foo(1).then(v => console.log(v)); //1
// async 함수 표현식
const bar = async function (n) { return n; }
bar(2).then(v => console.log(v)); //2
// async 화살표 함수
const baz = async n => n;
bar(3).then(v => console.log(v)); //3
// async 메서드
const obj = {
  async foo(n) { return n; }
};
obj.foo(3).then(v => console.log(v)); //4
//async 클래스 메서드
class MyClass {
  async bar(n) { return n; }
}
const mc = new MyClass();
mc.bar(5).then(v => console.log(v));class MyClass {
  async constructor() { } //syntaxError
}
const mc = new MyClass();awaitawait 키워드는 프로미스가 settled 상태가 될 때까지 대기하다가, settled 상태가 되면 프로미스가 resolve한 처리 결과를 반환한다.// Node.js 환경에서 window.fetch 함수를 사용하기 위함
const fetch = require('node-fetch');
const getGithubUserName = async id => {
  const res = await fetch(`https://api.github.com/users/${id}`);
  const { name } = await res.json();
  console.log(name); // jy Ssong
};
getGithubUserName('vSsongv');  fetch 함수가 비동기 처리가 완료될 때까지 대기하다가, 완료되면 resolve한 처리 결과가 res 변수에 할당된다. await 키워드는 다음 실행을 일시 중지시켰다가 프로미스가 settled 상태가 되면 다시 재개하는 것이다.await 키워드를 사용할 때, 서로 연관이 없이 개별적으로 수행되는 비동기 처리라면 순차적으로 처리할 필요가 없다.async function foo() {
  const res = await new Promise.all([
    new Promise(resolve => setTimeout(() => resolve(1), 3000)),
    new Promise(resolve => setTimeout(() => resolve(3), 3000)),
    new Promise(resolve => setTimeout(() => resolve(2), 3000)),
  ]);
  console.log([a, b, c]); //[1,2,3]
}
foo(); //약 3초 소요된다.bar함수같은 경우 비동기 처리의 함수 결과가 보장되어야 하므로 모든 프로미스에 await 키워드를 써서 순차적으로 처리해야 한다.async function bar() {
  const a = await new Promise(resolve => setTimeout(() => resolve(1), 3000));
  const b = await new Promise(resolve => setTimeout(() => resolve(a + 1), 3000));
  const c = await new Promise(resolve => setTimeout(() => resolve(b + 1), 3000));
  
  console.log([a, b, c]); //[1,2,3]
}
bar(); //약 6초 소요된다.try {
  setTimeout(() => { throw new Error('Error!'); }, 1000);
} catch (e) {
  // 에러를 캐치하지 못한다.
  console.error('캐치한 에러', e);
}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 reponse.json();
    console.log(data);
  } catch (err) {
    console.error(err); // TypeError: Failed to fetch
  }
};
foo();foo 함수의 catch 문은 HTTP 통신에서 발생한 네트워크 에러뿐 아니라 try 코드 블록 내의 모든 문에서 발생한 에러까지 모두 캐치할 수 있다.
catch 문을 사용해 에러 처리를 하지 않으면 async 함수는 에러를 reject하는 프로미스를 반환하기 때문에, Promise.prototype.catch 메서드를 사용해 에러를 캐치할 수도 있다.
const fetch = require('node-fetch');
const foo = async () => {
  const wrongUrl = 'https://wrong.url';
    
  const response = await fetch(wrongUrl);
  const data = await reponse.json();
  return data;
};
foo()
  .then(console.log)
  .catch(console.error); // TypeError: Failed to fetch<모던 자바스크립트 deepdive와, 추가 탐구한 내용을 정리한 포스트입니다.>