리코딩 : TIL

TIL : 프로미스(Promise) & async / await

BreezeBm 2020. 11. 26. 15:54

Photo by Womanizer WOW Tech on Unsplash

자바스크립트 비동기 처리를 위해서 콜백을 사용했었다. 하지만 콜백은 콜백지옥에 빠질 수 있고, 가독성이 떨어지고 에러가 발생하게 되면 골치 아파지기 때문에, 비동기 적으로 처리하는것에 어느정도 무리가 있다.

 

그래서 ES6에서는 비동기 처리를 위한 Promise가 두두등장! 그리고 ES7에서는 async / await이 두두등장! 오늘은 이렇게 두가지에 대해서 기록해보자!


 

1. 프로미스(Promise)

프로미스는 상태를 가진다.

  • pending(대기) : 비동기 처리가 아직 수행되지 않은 상태를 말한다. 아직까지 resolve나 reject가 실행되지 않은 상태

  • fulfilled(성공) : 비동기 처리가 수행이 되었고, resolve가 실행된 상태이다.

  • rejected(실패) : 비동기 처리가 수행이 되었지만 실패했고, reject가 실행된 상태이다.

프로미스틑 Promise생성자를 통해서 인스턴스를 만든다. Promise는 비동기 작업을 수행할 콜백함수를  콜백함수 인자로 전달 받는데 이 콜백함수는 resolve와 reject를 인자로 받는다. 

let example = new Promise((resolve, reject) => {
  if (// 수행 작업이 성공 했을 때) {
    resolve('good!')
  } else if (// 에러나, 수행작업이 실패 했을 때) {
    reject('bad!')
  }
})

비동기 처리가 성공하면 콜백 함수의 인자로 전달받은 resolve함수를 호출하게 되고, 이때 프로미스의 상태는 fulfilled(성공) 상태가 된다. 반대로 비동기 처리가 실패를 하게 되면, 콜백함수의 인자로 전달받은 rejcet가 호출하게 되고, 이 때 프로미스의 상태는 rejected(실패)가 된다.

프로미스로 구현된 비동기 함수는 프로미스를 반환하게 된다, 그래서 프로미스에는 후속처리 메소드가 있다. 바로 then과 catch이다. then은 계속해서 프로미스를 반환하기 때문에 쭉쭉 이어서 쓸 수 있고, catch는 말그대로 error가 있는 경우 잡아서 처리하는 에러핸들링이다. 

new Promise(function(resolve, reject) {
  setTimeout(() => resolve(2), 1000);
})
.then(result => {
  console.log(result); // 2
  return result * 2;
})
.then(result => { 
  console.log(result); // 4
  return result * 2;
})
.then(function(result) {
  console.log(result); // 8
})
.then(result => {
  throw new Error("에러!")
})
.catch(error => alert(error.message)) // 에러!

계속해서 프로미스가 then을 통해서 연결되어 지는 것을 볼 수 있다. 위의 코드는 순차적으로 2, 4, 8을 보여주고 에러가 던져지고, 에러 메세지를 창으로 띄어준다. 이때 .then으로 계속 연결되어 진것을 볼 수 있는데, 바로 프로미스 체이닝이다.

 

다음은 Promise.all이다. Promise.all은 프로미스가 담겨져 있는 배열 등의  iterable한 인자를 전달받는다.

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
])
.then(console.log) // [ 1, 2, 3 ]
.catch(console.log)

첫번째 프로미스는 3초 후에 1을 처리결과에 반환하고, 두번째는 2초후에 2를 3번째는 1초후에 3을 결과를 처리하고 반환을 한다. Promise.all은 모든 프로미스를 병렬로 처리하고, 모든 프로미스 처리가 종료될 때까지 기다린 후에 resolve 또는 reject를 한다.


2. async / awiat

ES7부터 추가된 이 문법을 사용하면 프로미스를 좀 더 편하게 사용할 수 있다. 

 

async는 function 앞에 위치 시켜서 사용하면 된다. 이때 함수 앞에 붙게 되면 프로미스를 반환하게 된다. 프로미스가 아닌 것은 프라미스로 감싸서 반환을 하게 된다. await의 경우에는 async함수 안에서만 동작하게 된다. 자바스크립트는 이 await이라는 친구를 만나게 되면 프라미스가 처리가 될 때 까지 기다렸다가 그 이후에 반환을 하게 됩니다.

async function showGood() {

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

  let result = await promise; // 프로미스가 처리될 때 까지 기다려

  alert(result); // "Good!"
}

showGood();

await 키워드를 만났기 때문에 해당하는 프로미스가 처리가 될 때 까지 이 함수는 실행을 기다리고 있다. 말그래도 await하고 있는 것이다. 프로미스가 처리 될때까지 다른 일을 할 수 있어서 효율적으로 처리가 가능하다. 그리고 이전에 보았던 then보다 가독성도 좋고, 쓰기도 쉽다.

 

 

다음은 무엇을 기록할까!