비동기(Asynchronous)

G_NooN·2024년 1월 27일
0

JavaScript

목록 보기
5/7

콜백 함수(Callback Function)

다른 함수의 인자로 들어가는 함수

콜백 함수를 인자로 받은 함수는 콜백 함수를 원하는 위치에서 원하는 시점에 호출할 수 있다.

콜백 함수의 인자

콜백 함수의 인자의 순서가 정해져 있는 경우가 있다.

/* 1. forEach, map, filter, find, ... */
Array.map(
  (function callback(currentElement, index, array) {...}), thisArg
);
// currentElement : 현재 처리하는/처리할 요소
// index : 현재 처리하는/처리할 요소의 인덱스
// array : 콜백 함수를 호출한 배열
// thisArg : 콜백 함수의 this 값

/* 2. reduce, reduceRight */
Array.reduce(
  (function callback(accumulator, currentValue, currentIndex, array) {...}), initialValue
);
// accumulator : 콜백 함수의 반환값(콜백의 이전 반환값 or initialValue)
// currentValue : 처리할 현재 요소
// currentIndex : 처리할 현재 요소의 인덱스
// array : 콜백 함수를 호출한 배열
// initialValue: 콜백 함수에 제공할 첫 번째 값

따라서, 해당 함수에서는 콜백 함수의 인자의 위치를 고려하여 작성해야 한다.

// 정상
[10, 20, 30].forEach((currentValue, index) => {
  console.log(`Index[${index}] = ${currentValue}`);
});

// 오류
[10, 20, 30].forEach((index, currentValue) => {
  console.log(`Index[${index}] = ${currentValue}`);
});
  • 출력 결과
정상오류
Index[0] = 10Index[10] = 0
Index[1] = 20Index[20] = 1
Index[2] = 30Index[30] = 2

콜백 함수는 함수다
콜백 함수가 객체의 메서드 형태로 존재하더라도, 호출할 땐 함수의 형태로 호출한다.

const obj = {
  num: [1, 2, 3],
  printNum: function(v, i) {
    console.log(this, v, i);
  }
};
obj.printNum("Value", "Index");
// { num: [ 1, 2, 3 ], printNum: [Function: printNum] } Value Index

콜백 함수의 this binding

콜백 함수의 기본 this 값은 콜백 함수를 호출하는 객체/함수다.

콜백 함수의 this 값을 변경하려는 경우, bind 메서드를 사용한다.

const obj2 = {
  num: [4, 5, 6]
}
obj.printNum.bind(obj2)("Value", "Index");
// { num: [ 4, 5, 6 ] } Value Index

비동기 제어

동기 vs 비동기

  • 동기(Synchronous)
    • 작업이 순차적으로 실행됨
    • 이전 코드가 완료되어야 다음 코드를 실행함
    • 따라서, 특정 코드의 실행 시간이 길면 길수록 다음 코드의 실행이 미뤄짐
  • 비동기(Asynchronous)
    • 이전 코드가 완료될 때까지 기다리지 않고 바로 다음 코드를 실행함

콜백 지옥(Callback Hell)

수많은 비동기 함수를 동기적(순차적)으로 수행하기 위해 콜백 함수를 중첩적으로 작성하여 가독성이 떨어지는 현상

// AS-IS (Callback Hell)
getData(function(a) {
  getMoreData(function(b) {
    getMoreData(function(c) {
      getMoreData(function(d) {...});
    });
  });
});

콜백 지옥 개선 방안(1) - Promise 객체 활용(ES6)

Promise 객체

비동기 연산을 수행하고 성공(Resolve) / 실패(Reject) 여부를 반환하는 객체

Promise 객체의 상태

  • Pending(대기 중) : 비동기 연산이 아직 수행되지 않은 상태
  • Fulfilled(수행 완료) : 비동기 연산이 성공적으로 수행되어 결과값을 반환한 상태
  • Rejected(거부됨) : 비동기 연산이 실패하거나 오류가 발생한 상태

Promise.all vs Promise.allSettled
: 여러 개의 Promise를 병렬로 수행한 뒤 전체 결과를 배열 형태로 반환함

  • 공통점
    • 모든 Promise가 완료될 때까지 기다림
  • 차이점
    • Promise.all
      • 모든 Promise가 Fulfilled인 경우에만 최종적으로 Fulfilled를 반환함
      • 단 하나의 Promise가 Rejected면, 최종적으로 Rejected로 반환함
    • Promise.allSettled
      • 각 Promise의 Fulfilled/Rejected 결과를 배열 형태로 반환함
      • Promise의 결과가 Fulfilled면 value를 반환하고, Rejected면 resaon을 반환함
      • 최종 결과를 Fulfilled와 Rejected로 나누어 각각 처리함

Promise를 활용한 비동기 연산의 동기적 처리(1) - Promise 형태로 변환

// TO-BE (Promise)
function getFinalData() {
  function getData() {
    return new Promise(function(resolve) {
      function(a) {
        resolve(resultA);
      }
    });
  }
  function getMoreData(resultA) {
    return new Promise(function(resolve) {
      function(b) {
        resolve(resultB);
      }
    });
  }
  function getMoreData(resultB) {
    return new Promise(function(resolve) {
      function(c) {
        resolve(resultC);
      }
    });
  }
  function getMoreData(resultC) {
    return new Promise(function(resolve) {
      function(d) {
        resolve(finalData);
      }
    });
  }
}

Promise를 활용한 비동기 연산의 동기적 처리(2) - then 활용

// TO-BE (Promise ~ then)
function getData() {
  return resultA;
}

function getFinalData() {
  getData()
  .then(function getMoreData(resultA) {
    return resultB;
  })
  .then(function getMoreData(resultB) {
    return resultC;
  })
  .then(function getMoreData(resultC) {
    return finalData;
  })
}

콜백 지옥 개선 방안(2) - async/await 문 활용(ES7)

비동기 작업을 수행할 함수 앞에 async 키워드를 입력하고,
내부에서 동기적으로 수행할 함수의 앞에 await 키워드를 입력함

// TO-BE (async/await)
async function getFinalData() {
  let resultA = await getData();
  let resultB = await getMoreData(resultA);
  let resultC = await getMoreData(resultB);
  let finalData = await getMoreData(resultC);
}
profile
쥐눈(Jin Hoon)

0개의 댓글