[JavaScript] 비동기 처리 및 Promise, async/await 개념

정다은·2022년 10월 31일
1
post-thumbnail

📌 참고
자바스크립트 비동기 처리와 콜백 함수
자바스크립트 Promise 쉽게 이해하기
자바스크립트 async와 await

🤔 비동기 처리란?

  • 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 자바스크립트의 특성
  • ex #1 jQuery ajax 통신
function getData() {
  let data;
  $.get('https://domain.com/products/1', function(response) {
    data = response;
  }); // 데이터를 요청하고 받아올 때까지 기다리는 것 ❌
  return data; // 해당 줄을 바로 실행 ⭕
}

console.log(getData()); // 🚨 response 값이 아닌 undefined 값이 찍힘 
  • ex #2 setTimout과 같이 JS Engine이 아닌 Web API 영역에 따로 정의되어 있는 함수
console.log("A");

setTimeout(function() {
  console.log("3 seconds passed"); // 3초 및 해당 줄의 출력을 기다리는 것 ❌
}, 3000);

console.log("B"); // 해당 줄을 바로 실행 ⭕

// 🚨 A - (3초 후) 3 seconds passed - B 순서가 아닌, A - B - (3초 후) 3 seconds passed 순서로 출력!
  • 그외에도 이벤트에 의해 실행되는 함수(핸들러), React의 useState 등이 비동기적으로 실행됨

💡 비동기 처리의 문제점 해결하기 - 콜백함수

비동기 처리를 원하지 않아요! 동기적으로 한 작업이 끝난 뒤 다른 작업을 실행시키고 싶어요! 할 때에는..?
👉 콜백함수를 통해 특정 로직이 끝났을 때 원하는 동작을 실행하도록 실행 순서를 보장할 수 있음

  • 콜백함수 다른 함수의 argument로 넘겨주는 함수를 말함
  • 콜백함수를 넘겨받은 함수는 해당 콜백함수를 필요에 따라 동기적 또는 비동기적으로 실행시킬 수 있음
// ex #1 jQuery ajax 통신이 동기적으로 이루어질 수 있도록 개선한 코드
function getData(callback) {
  $.get('https://domain.com/products/1', function(response) {
    callback(response);
  });
}

getData(function(data) {
  console.log(data);
}

🚨 콜백지옥이란?

  • 여러 비동기 처리 작업을 꼬리에 꼬리를 무는 형태로 실행해야할 때 콜백 안에 콜백을 계속 호출하는 식으로 코딩하게 되는 것
  • 낮은 가독성, 로직 변경의 어려움과 같은 문제점 존재
// 콜백지옥의 예시
$.get('url', function(response) {
  parseValue(response, function(id) {
    auth(id, function(result) {
      display(result, function(text) {
        console.log(text);
      });
    });
  });
});
  • 핸들러 함수를 분리하여 코딩 패턴만으로 가독성을 개선할 수 있음
function parseValueDone(id) {
  auth(id, authDone);
}
function authDone(result) {
  display(result, displayDone);
}
function displayDone(text) {
  console.log(text);
}
$.get('url', function(response) {
  parseValue(response, parseValueDone);
});
  • 그 외 해결방법은 Promise 또는 async & await

⭐ 콜백지옥 해결하기 - ① Promise

  • JS 비동기 처리에 사용되는 객체
  • 프로미스의 세 가지 상태
    • Pending(대기)
      • 비동기 처리 로직이 아직 완료되지 않은 상태
      • new Promise(); 메서드 호출 시 대기 상태
      • new Promise(function(resolve, reject) { … }); 와 같이 콜백 함수 선언 가능
    • Fulfilled(이행, 완료)
      • 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
      • 콜백 함수 인자 resolve 실행 시 이행 상태
      • 이행 상태가 되면 then()을 사용하여 처리 결과 값을 받을 수 있음
    • Rejected(실패)
      • 비동기 처리가 실패하거나 오류가 발생한 상태
      • 콜백 함수 인자 reject 실행 시 실패 상태
      • 실패 상태가 되면 catch()를 사용하여 실패 이유를 받을 수 있음
function func() {
  return new Promise(function(resolve, reject) {
    $.get('url', function(response) {
    if (response) resolve();
    reject(new Error("Request is failed"));
    });
  });
}

func().then(function(data) { // ✅ Fulfilled
  console.log(data); // response 값 출력
}).catch(function(error) { // 🚨 Rejected
  console.log(error); // 실패 이유 출력
});
  • Promise Chaining
    • 여러 개의 프로미스 연결하기
new Promise(function(resolve, reject){
  setTimeout(function() {
    resolve(1);
  }, 2000);
})
  .then(function(result) {
  console.log(result); // 1
  return result + 10;
})
  .then(function(result) {
  console.log(result); // 11
  return result + 20;
})
  .then(function(result) {
  console.log(result); // 31
});
  • 프로미스 에러 처리 방법
    • then()의 두 번째 인자로 에러를 처리하는 방법 → then()의 콜백 함수 내에서 발생한 오류를 제대로 잡아내지 못함
      • getData().then(handleSuccess, handleError);
    • catch()를 이용하는 방법 → 보다 효율적!
      • getData().then().catch();

⭐ 콜백지옥 해결하기 - ② async/await

  • 함수의 앞에 async 라는 예약어 붙이기
  • 함수 내부 로직 중 비동기 처리 코드 앞에 await 붙이기
    • 비동기 처리 메서드가 반드시 프로미스 객체를 반환해야 await가 의도한 대로 동작!
async function 함수명() {
	await 비동기_처리_메서드_명();
}
  • 예외 처리
    • try-catch 문 활용
profile
벨로그에는 주로 알고리즘 문제를 풀고 기록합니다 ✍

0개의 댓글