본문 바로가기

Front-end/JavaScript

[JavaScript] 비동기 - 콜백과 프로미스 객체

1. callback 함수

  • 다른 함수의 인수로 전달되는 함수입니다. 이러한 함수는 특정 작업이 완료된 후 호출되도록 설계되었습니다. 콜백 함수는 비동기 작업을 처리할 때 자주 사용되며, 이벤트 처리, 타이머 설정, 네트워크 요청 등에 활용됩니다.
  • 사용 예제

 

function a(callback) {
  setTimeout(() => {
    console.log('A');
    callback();
  }, 1000);
}

function b() {
  console.log('B');
}

a(() => b());

 

함수 a에서 함수 b를 callback이라는 인수로 받아와 호출하였습니다. 함수 a를 호출할 때도 전달자를 화살표 함수 혹은 일반 함수로 표현하여 함수 b를 호출할 수 있습니다.

function a(callback) {
  const str = 'Hello'
  setTimeout(() => {
    console.log('A');
    callback(str);
  }, 1000);
}

function b() {
  console.log('B');
}

a((event) => {
  console.log(event);
  b();
});

이처럼 callback 함수에 매개변수도 전달할 수 있습니다.

 

  • 콜백 지옥

이처럼 콜백 함수는 실행 순서를 보장해 줄 수 있지만 콜백함수가 늘어나면 늘어날수록 코드의 복잡성은 커지고 관리하기가 어려워질 수 있습니다.

function a(callback) {
  const str = 'Hello';
  setTimeout(() => {
    console.log('A');
    callback();
  }, 1000);
}

function b(callback) {
  setTimeout(() => {
    console.log('B');
    callback();
  }, 1000);
}

function c(callback) {
  setTimeout(() => {
    console.log('C');
    callback();
  }, 1000);
}

function d(callback) {
  setTimeout(() => {
    console.log('D');
    callback();
  }, 1000);
}

a(() => b(
    () => c(
        () => d(
            () => console.log('Done')
            )
        )
    )
);

이러한 단점들을 보완하기 위해서 es6부터 새롭게 도입된 Promise 객체를 사용해 보겠습니다.

 

2. Promise

  • 비동기 작업을 처리하는 데 사용되는 객체로, 작업의 성공 또는 실패를 나타내는 값을 처리하는 데 도움을 줍니다. Promise는 미래에 결과가 제공될 것이라는 약속을 나타내며, 콜백 함수의 단점을 보완하여 비동기 코드를 더 직관적이고 가독성 있게 만듭니다.
    • 대기 중(Pending): 초기 상태, 작업이 완료되지 않음
    • 이행됨(Fulfilled): 작업이 성공적으로 완료됨
    • 거부됨(Rejected): 작업이 실패함  
  • 사용 예제
function a() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('A');
      resolve('Hello A');
    }, 1000);
  });
}

function b() {
  console.log('B');
}

async function result() {
  const res = await a();
  console.log('res: ', res);
  b();
}

result();

함수 a에 promise 객체를 생성해서 resolve를 매개변수로 하여 로직 실행 후 특정 부분에서 매개변수가 실행되도록 정해줄 수 있습니다. 함수 result를 비동기로 선언하여 함수 a를 호출할 때 await를 붙여 a가 실행된 후 함수 b가 실행되도록 순서를 지정해 줄 수 있습니다.

 

  •  다중 함수 중복 처리
function a() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('A');
      resolve('Hello A');
    }, 1000);
  });
}

function b() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('B');
      resolve('Hello B');
    }, 1000);
  });
}

function c() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('C');
      resolve('Hello C');
    }, 1000);
  });
}

function d() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('D');
      resolve('Hello D');
    }, 1000);
  });
}

async function result() {
  const h1 = await a();
  const h2 = await b();
  const h3 = await c();
  const h4 = await d();
  console.log('Done!');
  console.log(h1, h2, h3, h4);
}

result();

위와 같이 콜백 함수로 호출 순서를 지정해 줬을 때보다 코드가 좀 더 직관적이고 가독성이 좋아진 것을 알 수 있습니다.

 

참고 문서: 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

'Front-end > JavaScript' 카테고리의 다른 글

[JavaScript] 비동기 - then, catch, finally  (2) 2024.08.07