[JavaScript] 비동기 처리의 시작, ㅋ..콜백.. callback 🤪

muz·2022년 1월 11일
0
post-thumbnail

JavaScript는 동기적인 언어이다. 호이스팅이 된 이후부터 코드가 작성한 순서에 따라 하나씩 동기적으로 실행되기 때문이다.

🤔 호이스팅? hoisting?
: 호이스팅이란 var 변수의 선언이나 함수 선언들이 가장 위로 올라가는 것을 의미한다.

JavaScript의 비동기?

그렇다면 JavaScript에서 말하는 '비동기' 란 무엇일까? 비동기는 언제 코드가 실행될 지 예측할 수 없는 것이다. 비동기의 좋은 예는 setTimeout()이 있다. 이는 지정한 시간이 지나면 전달한 콜백함수를 호출한다.

🤔 callback? 콜백함수?
: 콜백함수는 파라미터로 전달한 함수를 나중에 불러달라고 하는 것과 같다.

콜백함수 알아보기

setTimeout은 바로 실행되는 것이 아니라, 인자로 함수를 전달하고 있다. 그래서 지금 당장 실행하지는 않고, 정해진 시간이 지난 후에 파라미터로 전달한 함수를 실행한다. 보통 콜백함수는 arrow함수로 나타낸다.

console.log('1');
// setTimeout(function() { console.log('2');}, 1000); 
setTimeout(() => console.log('2'), 1000); // 1초 뒤에 2가 출력된다.
console.log('3');

// 결과
// 1
// 3
// 2

그렇다면 콜백은 항상 비동기일때에만 쓰는 것일까?

callback의 2가지 경우

1. synchronous callback

즉각적으로, 동기적으로 실행하는 콜백이다. 콜백을 파라미터 인자로 받아서, 이를 처리하는 함수를 만들어보자.

function printImmediately(write) { // 함수의 선언
	write();
}

printImmediately(() => console.log('hello'));

함수의 선언은 호이스팅이 되니 가장 위에서 실행되는 효과를 가진다.

2. asynchronous callback

나중에 언제 실행될 지 예측 불가능한 콜백이다.

function printWithDelay(print, timeout) { // setTimeout을 wrapping 하고 있는 함수 
 	setTimeout(print, timeout);  
}

printWithDelay(() => console.log('async callback'), 2000);

async callback은 2초뒤에 콘솔에 찍히게 된다.

callback Hell, 콜백 지옥

콜백지옥이란 끊임없이 콜백을 부르고 또 부르고,, 이렇게 작성된 코드를 일컫는 말이다. 콜백 체인의 문제점은 무엇일까?

  1. 가독성이 떨어지고, 한눈에 알아보기 어렵다.
  2. 로직 파악이 어렵고 유지 보수가 없다.
  3. 체인이 길어질수록 에러 발생확률이 높고 디버깅도 어려워진다.

직접 콜백 지옥에 빠져보다. 이번에는 백엔드로부터 데이터를 받아오는 클래스를 작성해보자.

class UserStorage {  
  loginUser(id, password, onSuccess, onError) {
    setTimeout(() => {
      if (
        (id === 'muz' && password === 'velogs')
      ) {
        onSuccess(id);
      } else {
        onError(new Error('not found'));
      }
    }, 2000);
  }

  // 성공 시 사용자의 데이터를 받아서 사용자의 역할을 서버에게 요청해서 받아옴
  getRoles(user, onSuccess, onError) { 
    setTimeout(() => {
      if (user === 'muz') {
        onSuccess({ name: 'muz', 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 => {
        console.log(
          `Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
        );
      },
      error => {
        console.log(error);
      }
    );
  },
  error => {
    console.log(error);
  }
);                               
profile
Life is what i make up it 💨

0개의 댓글