Language/JavaScript

async와 await

nayoon030303 2021. 7. 19. 05:11

async와 await

async와 await라는 특별한 문법을 사용하면 프라미스를 조금 더 편하게 사용할 수 있습니다.

async 함수 

async는 function앞에 위치합니다.

async function f(){
	return 1;
}

function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환합니다. 위 코드처럼 프라미스가 아니 값을 반환해도 이행 상태의 프라미스로 값을 감싸 이행된 프라미스가 반환되도록 합니다.

 

async function f(){
	return 1;
}

f().then(alert);

위 코드처럼 result가 1인 이행 프라미스가 반환됩니다. 

 

await

await는 async function안에서만 사용이 가능합니다.

let value = await promise

자바스크립트는 await 키워드를 만나면 프라미스가 처리될 때까지 기다립니다. 결과는 모든 처리가 끝난 후 반환됩니다. 

 

async function f(){
	let promise = new Promise((resolve,reject)=>{
    	setTimeout(()=>resolve("완료"),1000)
    });
	
    let result = await promise;
    
    alert(result);
}
    
 f();

await promise 부분에서 실행이 잠시 '중단'되었다가 프라미스가 처리되면 실행이 재개됩니다. 이때 프라미스 객체의 result 값이 변수 result에 할당됩니다. 위 코드는 1초 후 완료를 띄웁니다. 

 

awit는 promise.then보다 좀 더 세련되게 프라미스의 result값을 얻을 수 있도록 해주는 문법입니다. promise.then보다 가독성이 좋고 쓰기 쉽습니다. 

 

에러 핸들링

프라미스가 정상적으로 실행되면 await promise는 프라미스 객체의 result에 저장된 값을 반환합니다. 하지만 프라미스가 거부되면 throw문을 작성한 것처럼 에러가 던져집니다. 

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

위 코드와 아래 코드는 동일합니다. 

async function f(){
	throw new Error("에러 발생");
}

await가 던진 에러는 throw가 던진 에러를 잡을 때처럼 try...catch를 사용해 잡을 수 있습니다. 

async function f(url){
	try{
    	let response = await fetch(url);
     }catch(err){
     	alert(err);
     }
}

 

 

과제 

모던 자바스크립트 마지막에 어떤 챕터들은 과제가 나옵니다. 이번 async와 await에서 나왔던 과제들을 풀이해보겠습니다. 

 

1.async와 await를 사용하여 코드 변경하기

프라미스 체이닝 챕터의 예시 중 하나를 .then/catch 대신 async/await를 사용해 다시 작성해봅시다.

function loadJson(url) {
  return fetch(url)
    .then(response => {
      if (response.status == 200) {
        return response.json();
      } else {
        throw new Error(response.status);
      }
    })
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404

정답

async function loadJson(url) {

	let response = await fetch(url)
	if (response.status == 200) {
    	let json = await response.json();
        return json
     } else {
        throw new Error(response.status);
     }
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404
  1. loadJson 함수를 async함수로 바꿔줍니다. 
  2. 함수 안의. then을 await으로 바꿔줍니다. 
  3. loadJson에서 던지는 에러는. catch에서 처리됩니다. loadJson을 호출하는 코드는 async 함수 내부가 아니기 때문입니다. 

 

2. async가 아닌 함수에서 async 함수 호출하기

‘일반’ 함수가 하나 있는데, 여기서 async 함수를 어떻게 하면 호출하고, 그 결과를 사용할 수 있을까요?

async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  // ...코드...
  // async wait()를 호출하고 그 결과인 10을 얻을 때까지 기다리려면 어떻게 해야 할까요?
  // f는 일반 함수이기 때문에 여기선 'await'를 사용할 수 없다는 점에 주의하세요!
}

정답

async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  wait().then(result=>alert(result));
}
  1. async함수를 호출하면 promise를 반환하기 때문에 .then을 사용하면 됩니다.