자바스크립트는 동기적이다. 바로 호이스팅이 된 이후부터 코드가 동기적으로 실행된다는 뜻이다.
var, 함수 선언들이 자동적으로 제일 위로 올라가는 것을 의미한다. 호이스팅이 된 이후부터 코드가 나타나는 순서대로 자동적으로 실행된다.
console.log('1');
console.log('2');
console.log('3');
// 1 2 3 순차 출력
console.log('1');
setTimeout(() => console.log('2'), 1000); // 1초 후 실행
console.log('3');
// 1 3 2
💡 setTimeout을 만나면 브라우저 api니까 브라우저야 1초후에 실행해줘!
브라우저 API는 무조건 브라우저에게 요청을 보내게 된다.
/* ---- 기존 코드 ---- */
console.log('1');
setTimeout(() => console.log('2'), 1000); // 1초 후 실행
console.log('3');
/* ---- 추가된 코드 ---- */
function printImmediately(print) {
print();
}
printImmediately(() => console.log("hello"));
위 코드를 실행하면 자바스크립트 엔진은 아래와 같이 동작될 것이다.
// 함수의 선언은 호이스팅이 된다.
function printImmediately(print) {
print(); // ①
}
console.log('1'); // ② 출력
setTimeout(() => console.log('2'), 1000); // ③ 브라우저에게 요청 ⑥ 2 출력
console.log('3'); // ④ 출력
printImmediately(() => console.log("hello")); // ⑤ 함수호출
// 출력 : 1 3 hello 2
/* ---- 기존 코드 ---- */
console.log('1');
setTimeout(() => console.log('2'), 1000); // 1초 후 실행
console.log('3');
function printImmediately(print) {
print();
}
printImmediately(() => console.log("hello"));
/* ---- 추가된 코드 ---- */
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(() => console.log('async callback'), 2000); // 2초후 출력
위 코드를 실행하면 자바스크립트 엔진은 아래와 같이 동작될 것이다.
// 함수의 선언은 호이스팅이 된다.
function printImmediately(print) {
print();
}
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
console.log('1'); // 동기
setTimeout(() => console.log('2'), 1000); // 비동기
console.log('3'); // 동기
printImmediately(() => console.log("hello")); // 동기
printWithDelay(() => console.log('async callback'), 2000); // 비동기
// 출력 : 1 3 hello 2 async callback
서버는 따로 없기 때문에 타이머로 가상의 서버 통신 딜레이 시간을 부여했다.
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); //서버와 통신이 없기에 우리가 임의로 로그인이 2초 걸린다고 해보자.
}
// 사용자 데이터로 역할을 다시 서버에 요청해서 데이터 받아오는 함수
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if(user === 'ellie') {
onSuccess({name: 'ellie', role: 'admin'});
} else {
onError(new Error('no access'));
}
}, 1000);
}
}
아래는 콜백 체험 순서이다.
1. 사용자에게 id, password 입력 받기
2. 입력받은 값으로 서버에게 login 요청
3. 로그인 성공적이라면 로그인한 사용자 id를 다시 받아와서 Roles를 다시 요청
4. 역할이 성공적으로 받아와진다면 사용자의 이름, 역할을 출력
const userStorage = new UserStorage(); //클래스 선언
const id = prompt('enter your id'); // 사용자에게 id 입력받기
const password = prompt('enter your password'); // 사용자에게 password입력받기
// 받아온 값으로 로그인
userStorage.loginUser(id, password, (user) => {
userStorage.getRoles(user, (userWithRole) => {
alert(`Hello! ${userWithRole.name}, you have a ${userWithRole.role}`);
}, (error) => {
console.log(error); // 실패
});
},
error => {
console.log(error) // 실패
}
);
콜백안에서 또다른 콜백을 전달하고, 그 안에서 또 전달 전달.. 이게 바로 콜백지옥이다 😨