JavaScript

[새로운 기능] async와 await

  • -
반응형

비동기 작업을 처리할 때 async와 await 키워드를 이용할 수도 있다. async와 await는 ECMAScript 2017에 추가되어 Promise 보다도 더 따끈따끈하다.

기존 Promise의 답답함

앞서 살펴봤던 Promise는 잘 동작하지만 연계 동작을 처리하기 위해서는 then() then() 식으로 계속 chaining 해주는 과정이 필요하다.

function thenHell(init) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(init * 10);
    }, 1000);
  });
}

let result = thenHell(4)
  .then((val) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(val * 10);
      }, 1000);
    });
  })
  .then((val) => {
    console.log("then, then 후" + val);
  });

console.log("result ", result);

 

 

async and await

이 키워드들은 함수 앞에 사용하며 async는 비동기 함수를 만들 때, await는 비동기 코드를 호출할 때 사용한다.

바로 코드를 살펴보자.

async 키워드

일반적인 함수와 async가 적용된 함수를 만들고 각각 동작 결과를 살펴보자.

function normalfun() {
  return "Hello";
}

async function asyncfun() {
  return "hello async";
}

console.log(normalfun());   // Hello
console.log(asyncfun());    // fulfilled 상태의 Promise 객체

위 코드를 실행해보면 async가 붙은 함수는 자동으로 Promise 함수가 됨을 알 수 있다.

이제 asyncfun이 Promise임을 알았기 때문에 아래와 같이 쓰는 것이 너무 당연하다.

asyncfun().then((value) => console.log(value)); //hello async

 당연히 value에는 Promise에서 반환한 값이 전달된다.

 

await 키워드

await 는 Promise 객체 앞에 선언되며 반드시 async 함수 내에서만 사용할 수 있다. await 키워드가 호출되면 thread의 join 처럼 해당 작업이 끝나기 전까지 async의 메서드가 동작을 멈추고 기다린다. 또한 resolve의 파라미터가 Promise의 결과 값으로 활용된다. (아래의 예에서 await를 지우면 v1은 Promise 객체이고 await를 사용하면 init*10이다.)

async function mainfun(init) {
    console.log(`초기 값: ${init}`);
    let v1 = await new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`비동기 작업 진행 1`);
            resolve(init * 10);
        }, 1000);
    });

    console.log(`처음 비동기 작업 종료.. ${v1}`);
    let v2 = await new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`비동기 작업 진행 2`);
            resolve(v1 * 10);
        }, 1000);
    });
    console.log(`두 번째 비동기 작업 종료 ${v2}`);
    console.log("main fun end");
}

mainfun(5);
console.log("script over");

이제 두 번의 Promise를 호출하면서 별도의 then 문장이 없음에도 console에 순서대로 잘 출력됨을 확인할 수 있다.

resolve의 파라미터가 정상적인 동작의 반환이라면 reject의 파라미터는 예외를 발생시키는 이유가 된다. 이 예외는 try~catch 문장에서 처리할 수 있다.

다음 예는 arrow 함수에 async를 선언하고 이를 즉시 실행함수(괄호로 묶음)으로 만들어서 바로 실행하는 예이다.

(async () => {
  try {
    let ret = await new Promise((resolve, reject) => {
      setTimeout(() => {
        const rand = Math.random();
        console.log("기준 값:  ", rand);
        if (rand > 0.5) {
          resolve("0.5 초과 - 정상!");
        } else {
          reject("0.5 이하 - 비정상");
        }
      }, 1000);
    });
    // 정상 값의 활용
    console.log("ret: " + ret);
  } catch (error) {
    console.log("예외 발생 : " + error);
  } finally {
    console.log("어떻든 종료됨");
  }
})();

 

async, await를 활용한 영화 정보 가져오기

앞선 포스트에서 Promise만을 이용해서 가져왔던 영화 정보를 await, async 기반으로 수정해보자.

[es2015]-[Promise]03. 영화정보 조회 (tistory.com)

 

[es2015]-[Promise]03. 영화정보 조회

이번 포스트에서는 Promise 기반의 ajax 라이브러리인 axios를 이용해서 영화정보를 가져오는 것을 처리해보자. Promise를 활용한 영화 정보 가져오기 영화진흥위원회 API의 구성 영화진흥위원회에서

goodteacher.tistory.com

 

await, async 활용

위 코드를 await, async로 변경해보면 아래와 같다.

(async () => {
  const movieCdResult = await instance.get("/boxoffice/searchDailyBoxOfficeList.json", {
    params: {
      ...baseParam,
      targetDt: "20191120",
    },
  });
  const movieCd = movieCdResult.data.boxOfficeResult.dailyBoxOfficeList[0].movieCd;

  const companyCdResult = await instance.get("/movie/searchMovieInfo.json", {
    params: {
      ...baseParam,
      movieCd: movieCd,
    },
  });
  const companyCd = companyCdResult.data.movieInfoResult.movieInfo.companys[0].companyCd;

  const filmosResult = await instance.get("/company/searchCompanyInfo.json", {
    params: {
      ...baseParam,
      companyCd: companyCd,
    },
  });

  console.log("filmos: ", filmosResult.data.companyInfoResult.companyInfo.filmos);
})();

훨씬 간결한 코드로 동일한 효과를 볼수 있다.

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.