web/HTML+CSS+JS

Promise 문법 & async/await 문법

민사민서 2023. 4. 26. 16:47

- 비동기 작업을 콜백함수로만 처리하려다보니 콜백 피라미드 형태의 코드들 등장 (복잡쓰..)

ex) 숫자 n 을 파라미터로 받아와서 다섯번에 걸쳐 1초마다 1씩 더해서 출력하는 작업을 setTimeout 으로 구현

function increaseAndPrint(n, callback) {
  setTimeout(() => {
    const increased = n + 1;
    console.log(increased);
    if (callback) {
      callback(increased);
    }
  }, 1000);
}

increaseAndPrint(0, n => {
  increaseAndPrint(n, n => {
    increaseAndPrint(n, n => {
      increaseAndPrint(n, n => {
        increaseAndPrint(n, n => {
          console.log('끝!');
        });
      });
    });
  });
});

ex) 반복적인 LoadLink...

 

Promise를 사용하면 비동기 작업의 개수가 많아져도 코드의 깊이가 깊어지지 않게 된

function increaseAndPrint(n) {
    return new Promise((resolve, reject) => {
        const val = n;
        setTimeout(()=> {
            if(val==5) {
                reject(new Error(`It's five now!`));
            } else {
                console.log(val);
                resolve(val+1);
            }
        },1000);
    });
}

increaseAndPrint(1)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .catch(e=> {
        console.error(e);
    });

ex) then / catch의 사용

단점? 

- 에러를 잡을 때 몇번째에서 발생했는지 알아내기 어려움

- 특정 조건에 따라 분기를 나누기 어려움

- 특정 값을 공유해가면서 작업을 처리하기도 까다로움

 

async/await 문법은 ES8에 해당하는 문법으로서, Promise 를 더욱 쉽게 사용 할 수 있게 해줍니다

async function 함수명() {
  await 비동기_처리_메서드_명();
}

- 함수를 선언 할 때 함수의 앞부분에 async 키워드 붙이자

- 그리고 Promise 의 앞부분에 await 을 넣어주면 해당 프로미스가 끝날때까지 기다렸다가 다음 작업 수행

- 주의할 점은 비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await가 의도한 대로 동작한다.

 

예시)

function fetchItems() {
  return new Promise(function(resolve, reject) {
    var items = [1,2,3];
    resolve(items)
  });
}

async function logItems() {
  var resultItems = await fetchItems();
  console.log(resultItems); // [1,2,3]
}

- fetchItems() 함수는 프로미스 객체를 반환하는 함수

- 프로미스는 “자바스크립트 비동기 처리를 위한 객체

- fetchItems() 함수를 실행하면 프로미스가 이행(Resolved)되며 결과 값은 items 배열이 됨

// 'await' 키워드에 의해 Promise가 resolve될때까지 대기하다가 resolved value(resolve의 파라미터)를 리턴받음

 

- 실용 예제

function fetchUser() {
  var url = 'https://jsonplaceholder.typicode.com/users/1'
  return fetch(url).then(function(response) {
    return response.json();
  });
}

function fetchTodo() {
  var url = 'https://jsonplaceholder.typicode.com/todos/1';
  return fetch(url).then(function(response) {
    return response.json();
  });
}

- async & await 문법이 가장 빛을 발하는 순간은 여러 개의 비동기 처리 코드를 다룰 때입니다.

- 각각 사용자와 할 일 목록을 받아오는 HTTP 통신 코드가 있다고 하겠습니다.

- 위 함수들을 실행하면 각각 사용자 정보와 할 일 정보가 담긴 프로미스 객체가 반환됩니다

 

자 이제 이 두 함수를 이용하여 할 일 제목을 출력해보겠습니다. 살펴볼 예제 코드의 로직은 아래와 같습니다.

  1. fetchUser()를 이용하여 사용자 정보 호출
  2. 받아온 사용자 아이디가 1이면 할 일 정보 호출
  3. 받아온 할 일 정보의 제목을 콘솔에 출력
async function logTodoTitle() {
  try {
    var user = await fetchUser();
    if (user.id === 1) {
      var todo = await fetchTodo();
      console.log(todo.title); // delectus aut autem
    }
  } catch (error) {
    console.log(error);
  }
}

async await 문법을 이용하면 기존의 비동기 처리 코드 방식으로 사고하지 않아도 되는 장점이 생깁니다.