/ JAVASCRIPT

JavaScript(9) - callback

JavaScript 관련 포스팅

Synchronous vs. Asynchronous

Synchronous(동기적)

  • JavaScript는 synchronous(동기적)
    • hoisting이 된 이후부터, 코드 작성 순서에 맞추어 동기적으로 실행됨
    • hoisting이란?
      var, function declararion 은 선언 지점과 상관 없이 JS engine에 의해 문서의 최상단으로 끌어올려짐
      console.log('1');
      console.log('2');
      console.log('3');
    
    Console

    1
    2
    3

Asynchronous (비동기적)

  • 언제 코드가 실행될 지 예측 불가
    e.g.) setTimeout(): 지정한 시간이 지나면 전달한 callback fn을 호출함
      function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number
    
      console.log('1');
      setTimeout(function() {
          console.log('2');
      }, 1000);
      console.log('3');
    

    코드를 순차적으로 읽어감

    console.log(’1’); 실행
    setTimeout() 을 만나 1000ms(=1sec) 뒤 callback fn 실행 요청
    console.log(’3’) 실행
    → 1초 뒤 console.log(’2’) 실행

(tip) 위의 callback fn는 arrow fn으로 바꿔 쓸 수 있음

console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');

Callback fn

  • 나중에 다시(back) 부르는(call) 함수
  • synchronousasynchronous 두 가지가 존재함

Synchronous callback

function printImmediately(print) {
    print();
}
printImmediately(() => console.log('hello'));

Asynchronous callback

function printWithDelay(print, timeout) {
    setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'), 2000);

Result

console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');

// Synchronous callback
function printImmediately(print) {
    print();
}
printImmediately(() => console.log('hello'));

// Asynchronous callback
function printWithDelay(print, timeout) {
    setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'), 2000);
  • 코드 실행순으로 코드 나열을 다시 해보면,

      function printImmediately(print) { // hoisting
          print();
      }
    
      function printWithDelay(print, timeout) { // hoisting
          setTimeout(print, timeout);
      }
    
      console.log('1'); // 동기
      setTimeout(() => console.log('2'), 1000); // 비동기
      console.log('3'); // 동기
      printImmediately(() => console.log('hello')); // 동기
      printWithDelay(()=> console.log('async callback'), 2000); // 비동기
    

    function declaration은 hoist되므로 코드 최상단으로 끌어올려짐
    function printImmediatelyfunction printWithDelay가 상단으로 이동
    이후 코드들을 순서대로 실행함
    ‘1 → 3 → hello → 2 → async callback’ 순으로 console이 찍힘

Callback hell example

class UserStorage {
    loginUser(id, password, onSuccess, onError) {
        setTimeout(() => {
            if((id === 'minji' && password === 'pass') ||
            (id === 'someone' && password === 'pass too')
            ) {
                onSuccess(id);
            } else {
                onError(new Error('not found'));
            }
        }, 2000);
    }
    getRoles(user, onSuccess, onError) {
        setTimeout(() => {
            if(user === 'minji') {
                onSuccess({ name: 'minji', role: 'admin' });
            } else {
                onError(new Error('no access'));
            }
        }, 1000);
    }
}
  1. 사용자에게 idpassword를 입력 받음
  2. 서버에 login
  3. login이 성공적이라면 해당 id를 받아와 role 요청
  4. role을 성공적으로 받아오면 namerole이 있는 사용자의 object를 출력
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
    id, 
    password, 
    user => {
        userStorage.getRoles(
            user,
            userWithRole => {
                alert(`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
            }, 
            error => {
                console.log(error);
            } 
            );
    }, 
    error => {console.log(error)});

문제점

  1. 가독성이 떨어짐
  2. error, debugging, 유지 보수가 어려움

< 출처 >

“자바스크립트 11. 비동기 처리의 시작 콜백 이해하기, 콜백 지옥 체험 😱 JavaScript Callback | 프론트엔드 개발자 입문편 (JavaScript ES6),” 유튜브 비디오, 21:15, 게시자 “드림코딩 by 엘리,” 2020년 6월 9일, https://youtu.be/tJieVCgGzhs