콜백
비동기적 처리에 대해서 
1 2 3 4 5 6 7
   | function loadScript(src) {         let script = document.createElement('script');   script.src = src;   document.head.append(script); }
  | 
 
1 2
   |  loadScript('/my/script.js');
 
  | 
 
loadScript 는 비동기적으로 실행된다. 
loadScript()아래에 있는 코드들은 loadScript 가 실행되는 것을 기달려 주지 않고 바로 실행 됨. 
1 2 3
   | loadScript('/my/script.js'); 
  newFunction(); 
  | 
 
newFunction은 loadScript 안에 있으니가 아직 생성 되지 않았을 것이다. 
현재로서는 loadScript가 완료 됬는지 알 수 있는 방법이 없다. 
loadScript가 완료되면 원하는 함수를 실행 시키기 위해서 콜백 함수를 추가 행야 한다. 
1 2 3 4 5 6 7 8
   | function loadScript(src, callback) {   let script = document.createElement('script');   script.src = src;
    script.onload = () => callback(script);
    document.head.append(script); }
  | 
 
1 2 3 4 5
   | loadScript('/my/script.js', function() {      newFunction();    ... });
  | 
 
실제 사용 예시
1 2 3 4 5 6 7 8 9 10 11
   | function loadScript(src, callback) {   let script = document.createElement('script');   script.src = src;   script.onload = () => callback(script);   document.head.append(script); }
  loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => {   alert(`${script.src}가 로드되었습니다.`);   alert( _ );  });
  | 
 
무언가 비동기적으로 처리되는 함수는 처리가 끝난 이후 동작할 함수를 반드시 인수로 제공해야 한다. 
콜백 속 콜백
첫번째 스크립트를 읽은후 순차적으로 스크립트를 읽고 싶다면 어떻게 처리해야 할까?
콜백 함수 안에 두번째 loadScript를 호출하면 된다. 
1 2 3 4 5 6 7 8 9
   | loadScript('/my/script.js', function(script) {
    alert(`${script.src}을 로딩했습니다. 이젠, 다음 스크립트를 로딩합시다.`);
    loadScript('/my/script2.js', function(script) {     alert(`두 번째 스크립트를 성공적으로 로딩했습니다.`);   });
  });
  | 
 
만약 3개라면?
1 2 3 4 5 6 7 8 9 10 11
   | loadScript('/my/script.js', function(script) {
    loadScript('/my/script2.js', function(script) {
      loadScript('/my/script3.js', function(script) {            });
    })
  });
  | 
 
만약 갯수가 굉장히 많아진다면??
이렇게 작성히는 것은 적을때는 가능하지만 많을때는 좋은 방법이 아니다..
에러 핸들링
스크립트 로딩이 실패했을때 에러 핸들링 추가
1 2 3 4 5 6 7 8 9
   | 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); }
  | 
 
사용
1 2 3 4 5 6 7
   | loadScript('/my/script.js', function(error, script) {   if (error) {        } else {        } });
  | 
 
이런 패턴을 오류 우선 콜백(error-first callback) 이라고 한다. 
첫 번째 인수는 에러를 위해 남겨 둔다. 두번재 부터 여러개 추가 할 수 있음. 이렇게 하면 에러 케이스와 성공 케이스 모두 처리 가능하게 된다. 
멸망의 피라미드
언뜻 좋아 보이지만 여러개가 반복되면 콜백 지옥이 발생한다. 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | 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 {                        }         });
        }     })   } });
  | 
 
각 동작을 독립적인 함수로 만들어 완화하도록 한다. 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
   | 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 {        } };
  | 
 
사실 이렇게 작성해도 보기 불편한건 사실이고, 함수를 만들었는데 단지 콜백 지옥을 피하기 위해서만 만들었기 때문에 재사용이 불가능하다. 
가장 좋은 방법은 프로 미스를 사용하는 방법인데 다음 포스팅에서 설명하도록 한다.