하다보니

비동기 처리의 시작 콜백 이해하기 본문

프로그래밍 언어/JavaScript

비동기 처리의 시작 콜백 이해하기

claire 2022. 1. 21. 13:06

자바스크립트는 동기적인 언어이다.

한 작업이 실행되는 동안 다른 작업은 멈춘 상태를 유지하고 자신의 차례를 기다리는 것을 말한다. 

hoisting이 된 이후로부터 작성한 순서대로 나씩 실행된다는 말이다. 

Memory heap과 call stack은 자바스크립트 엔진의 주요 구성 요소이다. 

memory heap이란? - 변수와 객체의 메모리 할당을 담당하는 곳을 말한다. 

call stack이란? - 함수가 호출되면 쌓이는 것이다. 대신 함수가 쌓이는 순서와 반대로 실행된다. 

 

자바스크립트의 비동기 처리 작동원리는 여기를 참고해라.

https://ljtaek2.tistory.com/142

 

asynchronous는 비동기적으로 언제 코드가 실행될지 모르는 것이다.

어떠한 요청을 보내면 그 요청이 끝날 때까지 기다리는 것이 아니라 응답에 관계없이 바로 다음 동작이 실행되는 방식을 말한다. 

setTimeout은 전달한 콜백 함수를 일정 시간이 지나면 실행하는 것이다.

// JavaScript is synchronous.
// Execute the code block by orger after hoisting.
// hoisting: var, function declaration
console.log('1');					//동기
setTimeout(() => console.log('2'), 1000);    //브라우저 api는 브라우저에 요청을 보낸다. 비동기
console.log('3');					//동기

//콜백도 동기적과 비동기적 2가지가 있다. 

// 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);   //비동기

언어마다 콜백을 지원하는 방식이 다양하다. 

 

콜백 지옥. 콜백 함수 내에서 계속 콜백 함수를 호출하는 것. 콜백 지옥 예제 체험. 

 

// Callback Hell example
class UserStorage {
  loginUser(id, password, onSuccess, onError) {
    setTimeout(() => {
      if (
        (id === 'ellie' && password === 'dream') ||
        (id === 'coder' && password === 'academy')
      ) {
        onSuccess(id);
      } else {
        onError(new Error('not found'));
      }
    }, 2000);
  }

  getRoles(user, onSuccess, onError) {
    setTimeout(() => {
      if (user === 'ellie') {
        onSuccess({ name: 'ellie', role: 'admin' });
      } else {
        onError(new Error('no access'));
      }
    }, 1000);
  }
}

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);
  }
);

가독성이 너무 떨어진다. 어떻게 연결되어있는지 파악도 힘들고 비즈니스 로직을 한눈에 보기 힘들다. 디버깅을 해야 하는 경우에도 어디서 문제가 있는지 파악하기 힘들다. 유지 보수도 힘들다.