콜백

Vorhandenheit ·2021년 9월 27일
0

JS.코어

목록 보기
22/29
post-custom-banner

콜백

먼저, 비동기 동작처리

function loadScript(src) {
  let script = document.createElement('script');
  script.src = src;
  document.head.append(script);
}
// <script> 태그를 만들고 페이지에 태그를 추가합니다.
// 태그가 페이지에 추가되면 src에 있는 스크립트를 로딩하고 실행합니다.

함수 loadScript<script src = "...">을 동적으로 만들고 이를 문서에 추가함
브라우저는 자동으로 태그에 있는 스크립트를 불러오고, 로딩이 완료되면 스크립트를 실행함

이 때, 스크립트는 '비동기적'으로 실행됨, 로딩은 당장 시작되어도 실행은 함수가 끝난 후에야 되기 때문

만약 스크립트 로딩이 끝나자마자 스크립트를 사용해 무언가를 해야만한다면, 함수가 존재하지않는다는 에러가 발생함

왜냐하면 브라우저가 스크립트를 읽어올 시간을 확보하지 못했기 때문

이런 경우에 콜백함수를 사용함

  • 콜백함수 : 나중에 호출할 함수를 의미
function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;
  script.onload = () => callback(script);
  document.head.append(script);
} 
loadScript('/my/script.js', function() {
  // 콜백 함수는 스크립트 로드가 끝나면 실행됩니다.
  newFunction(); // 이제 함수 호출이 제대로 동작합니다.
  ...
});

두 번째 인수로 전달된 함수는 원하는 동작이 완료되었을 떄 실행됨

2. 콜백 속 콜백

스크립트가 두 개 있는 경우, 두 번쨰 스크립트 로딩은 첫 번쨰 스크립트 로딩이 끝난 이후가 되길 원하면 콜백 함수 안에서 두 번째 loadScript를 호출하느 ㄴ것

loadScript('/my/script.js', function(script) {

  alert(`${script.src}을 로딩했습니다. 이젠, 다음 스크립트를 로딩합시다.`);

  loadScript('/my/script2.js', function(script) {
    alert(`두 번째 스크립트를 성공적으로 로딩했습니다.`);
  });

});

중첩 콜백을 만들면 바깥에 위치한 loadSciprt가 완료된 후, 안쪽 loadScript가 실행됨

3. 에러 핸들링

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`${src}를 불러오는 도중에 에러가 발생했습니다.`));

  document.head.append(script);
}
loadScript('/my/script.js', function(error, script) {
  if (error) {
    // 에러 처리
  } else {
    // 스크립트 로딩이 성공적으로 끝남
  }
});

오류 우선 콜백 : 에러를 처리하는 흔히 사용되는 방식

  • callback 첫 번째 인수는 에러를 위해 남겨둠, 에러가 발생하면 이 인수를 이용해 callback(err)이 호출
  • 두 번째 인수는 에러가 발생하지 않았을 떄를 위하여 남겨둠

4. 멸망의 피라미드

깊은 중첩 코드가 만들어내는 패턴을 소위 콜백 지옥 , 멸망의 피라미드 라고 불림

loadScript('1.js', function(error, script) {

  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', function(error, script) {
      if (error) {
        handleError(error);
      } else {
        // ...
        loadScript('3.js', function(error, script) {
          if (error) {
            handleError(error);
          } else {
            // 모든 스크립트가 로딩된 후, 실행 흐름이 이어집니다. (*)
          }
        });

      }
    })
  }
});

이러한 문제를 해결하기 위해서는 독립적인 함수로 만들어 위와 같은 문제를 완화할 수 있음

loadScript('1.js', step1);

function step1(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', step2);
  }
}

function step2(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('3.js', step3);
  }
}

function step3(error, script) {
  if (error) {
    handleError(error);
  } else {
    // 모든 스크립트가 로딩되면 다른 동작을 수행합니다. (*)
  }
};
profile
읽고 기록하고 고민하고 사용하고 개발하자!
post-custom-banner

0개의 댓글