[JavaScript] 비동기 처리를 위해 등장한 Promise에 대해 알아보자 (+ async, await 과의 차이)

Brandon·2023년 6월 12일
0

이미지출처_linuxhint

Promise란 ?

콜백 지옥의 문제점을 해결하기 위해 ES6에서 도입되면서 등장하였다.

  • 비동기함수의 실행결과값을 담은 객체이며,
  • new Promise 생성자로 생성할 수 있으나, 일반적으로 fetch 함수를 사용하면서 많이 접하게 된다.
  • fetch 함수는 HTTP 응답을 나타낸 response 객체를 래핑한 Promise 객체를 반환한다.
  • 인자로는 성공시 호출되는 resolve 함수와 실패 시 호출되는 reject 함수를 받는다.
  • 프로미스는 비동기처리에 대한 상태정보를 갖는다.
    • pending
    • fulfilled ⇒ resolve 함수 호출
    • rejected ⇒ reject 함수 호출
const promise = new Promise((resolve, reject) => {
	if (){
		resolve("success");
	} else {
		reject("fail");
	}
});

callback 함수?

  • 정의 : 다른 함수의 인자로서 오는 함수
  • 특정 로직이 모두 실행되고나서, 함수를 실행하고자 할 때 콜백함수를 활용한다.

대표적으로 콜백함수를 활용하는 예시로서, 우리가 자주사용하는 Array.filter() 메서드가 있다.

  • 자바스크립트는 싱글스레드로서, 특정 로직의 연산이 끝나지 않더라도 다음 코드를 이어서 실행하는 특성이 있다.
  • 이러한 특성으로 인해, 비동기적으로 처리되는 로직은 동기적으로 처리되는 로직들 이후에 처리되곤 한다.
  • 하지만 콜백함수는, 앞에서 언급했다시피 앞의 로직을 순차적으로 처리하는 성격이 있기 때문에 비동기처리를 위해 콜백함수를 활용할 수 있다.
function fn() {
  console.log('하나');
  setTimeout(() => console.log('둘'), 0);
  console.log('셋');
}
fn(); // 결과 순서 => '하나', '셋', '둘'

callback hell

  • 계속해서 콜백패턴으로 비동기 처리를 하다보면, 코드의 가독성이 떨어져 의미를 알아보기 어려워지는 것을 말한다.
  • 비동기 함수는 비동기 처리 결과를 외부에 반환할 수 없고, 상위 스코프 변수에 할당할 수도 없다. 비동기 함수의 처리결과에 대한 후속 처리는 오로지 비동기 함수 내부에서 처리해야한다. 이때, 비동기 처리결과에 대한 후속 처리를 수행하기 위해 콜백함수가 전달된다.
  • 그런데 이 처리결과를 바탕으로 또다시 비동기 함수를 호출해야한다면, 콜백함수가 중첩되어 엄청나게 복잡한 코드가 생겨나게 된다.
function fn() {
    setTimeout(() => {
        console.log('하나');
        setTimeout(() => {
            console.log('둘');
            setTimeout(() => {
                console.log('셋');
            }, 0);
        }, 0);
    }, 0);
}
fn(); // 결과 순서 => '하나', '둘', '셋'

Promise를 활용한 콜백지옥 해결

function fn() {
  new Promise((resolve, reject) => {
    console.log('하나');
    // 실패인 경우 reject() 함수를 호출하면 된다.
    // 그러면 then()을 건너뛰고 catch()가 실행된다.
    resolve(); 
  })
  .then(() => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('둘');
        resolve();
      }, 0);
    });
  })
  .then(() => {
    console.log('셋');
  })
  .catch((err) => {
    console.log('err ', err);
  });
}

Promise를 쓰면 어떤 차이가 있는가? (vs Callback 패턴과의 차이)

  • Promise는 Callback 과 달리 결과값을 반환하여 전달할 수 있다.
  • Promise는 Promise 객체를 반환한다.
  • Promise는 호출될 때 바로 실행되지만, 그 안에 인자로 들어간 콜백은 resolve, reject 둘 중 하나가 호출되기 전엔 then 이나 catch로 넘어가지 않는다. 콜백패턴 대비 에러처리가 상대적으로 용이하다.
try {
	setTimeout(() => {throw new Error('Error');}, 1000);
} catch (e) {
	// 에러캐치하지 못함
	console.error(e);
}
  • 후속처리를 .then() .catch() .finally() 메서드를 통해 비교적 깔끔하게 처리할 수 있다. 후속처리 메서드 또한 후속 처리에 인자로 들어간 콜백 함수의 프로미스를 반환한다. 그래서 이어서 .then() → .then() → .catch() → .finally() 형태로 연속적으로 메서드를 호출할 수 있다. 이를 프로미스 체이닝이라고 한다.

async, await와의 차이

  1. 에러핸들링
  • Promise의 에러처리는 .catch()를 통해 이뤄진다.
  • Promise를 연속적으로 처리하는 코드의 경우에는 에러가 발생한 지점을 정확하게 찾기 힘들다.
  • async/await은 try…catch문을 활용해야한다.
  1. 체이닝
  • Promise는 .then()을 통해 promise 객체를 이어받아야한다.
  • async/await은 앞에 async와 await을 붙여준다는 차이가 있을뿐, 코드 자체는 동기적 흐름과 동일하게 작성해주면 된다. 조금 더 간결하게 코드를 작성할 수 있다.
profile
메인 블로그 이관하였습니다. https://dr-dev.tistory.com/

0개의 댓글

관련 채용 정보