function addCallback() {
setTimeout(() => {
let sum = 1 + 1;
console.log(sum);
}, 2000); //2초뒤에 이코드가 실행
}
addCallback();
console.log("end");
<예상 출력결과>
2
end
출력될 것 같지만 아니다.
<정답 출력결과>
end
2
end가 먼저 출력되는 이유는?
자바스크립트는 동기적이지만 setTimeout()과 같이 비동기로 처리되는 것에 영향을 받게되면 실행순서가 밀리게 된다. ( 자바스크립트 동작원리 참고 / 추후 작성예정 )
비동기란? 언제 코드가 실행될 지 예측할 수 없는것이다.
콜백함수는 비동기 방식의 문제로 등장했다고 하니, 당연히 비동기의 반대가 된다.
콜백함수는 "코드의 실행을 기다려주기 위해 존재하는 함수"이다.
function addCallback(fn) {
setTimeout(() => {
let sum = 1 + 1;
console.log(sum);
fn();
}, 2000); //2초뒤에 이코드가 실행
}
addCallback(function () {
console.log("end");
});
<출력>
2
end
만약 계속해서 콜백 콜백 콜백을 부르게 된다면,,,,, 지옥을 맛볼것이다!!!
아래 코드의 경우 큰 틀로 보자면,
1) prompt로 사용자 id 와 password를 입력받는다.
2) 아이디와 비밀번호가 매칭된다면, getRole 함수를 호출하여 해당 계정의 역할을 alert 창으로 보여준다.
>> 이것을 callback 함수를 활용
//Callback Hell example
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if (
(id === "hyejin" && password === "dream") ||
(id === "corder" && password === "academy")
) {
onSuccess(id);
} else {
onError(new Error("not found"));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === "hyejin") {
onSuccess({ name: "hyejin", role: "admin" });
} else {
onError(new Error("no access"));
}
}, 1000);
}
}
//id와 password를 Prompt를 이용해 입력받는다.
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your password");
userStorage.loginUser(
id,
password,
(user) => {
console.log("loginUser onSuccess"); //
userStorage.getRoles(
user,
(userWithRole) => {
console.log("getRoles onSuccess"); //
alert(`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
},
(error) => {
console.log(error);
}
);
},
(error) => {
console.log(error);
}
);
콜백함수 부분만 떼어놓고 보자 !
우선 코드 작성할 때도 내가 작성하기도 헷갈렸고,
작성하지 않는 사람이 보기에 이해하기가 쉽지 않다고 바로 느껴졌다.
가독성이 너무 떨어져서 어떻게 연결되는지 한번에 보기가 어려운 문제점이있다.
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (
(id === "hyejin" && password === "dream") ||
(id === "corder" && password === "academy")
) {
resolve(id);
} else {
reject(new Error("not found"));
}
}, 2000);
});
}
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === "hyejin") {
resolve({ name: "hyejin", role: "admin" });
} else {
reject(new Error("no access"));
}
}, 1000);
});
}
}
//prompt로 id password 입력받기.
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your password");
userStorage
.loginUser(id, password)
.then(userStorage.getRoles) //.then((id)=>userStorage.getRoles(id))
.then((user) => alert(`Hello ${user.name}, you have a ${user.role} role`))
.catch(colsole.log); // .catch((e) => colsole.log(e));
맨 아래를 보게될 경우, 간략해질 뿐 아니라 가독성까지 좋게 변했다.