● 콜백 함수는 늘 비동기일까?
function printImmediately(print) {
print();
}
function printDelay(print, delay) {
setTimeout(print, delay);
}
printDelay(() => {
console.log("asyncCallback");
}, 2000);
printImmediately(() => {
console.log("daeun");
});
printImmediately 함수는 콜백함수를 받고, 그 콜백함수를 바로 실행한다.
printDelay함수는 콜백함수와 delay할 함수를 받고, setTimeout로 콜백함수를 실행한다.
결과는 asyncCallback, daeun 순으로 출력된다.
즉, 콜백함수는 동기콜백함수와 비동기콜백함수 둘다 존재한다.
● 콜백 헬이 무엇일까?
class UserStorage {
//loginUser 메서드는 id와 password를 받고 로그인 성공하면 onSuccess, 실패하면 onError을 실행한다.
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if (
(id === "daeun" && password === "sleep") ||
(id === "zzapdaeun" && password === "clonedaeun")
) {
onSuccess(id);
} else {
onError(new Error("not found"));
}
}, 2000);
}
//getRoles 메서드는 로그인 성공시 유저의 name과 role을 성공콜백함수에 인자로 넣어주고 아니면 에러를 띄워준다.
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === "daeun") {
onSuccess({ name: "daeun", role: "admin" });
} else {
onError(new Error("no access"));
}
}, 2000);
}
}
위와같은 로그인 시스템이 있다고 칠때,
저 클래스를 활용해 인스턴스를 만들어보자.
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}`);
},
(error) => {
console.log(error);
}
);
},
(error) => {
console.log(error);
}
);
id와 password는 prompt로 입력값을 받고 난 뒤, 메서드의 매개변수로 넣어주고, 콜백함수도 각각 적어준다.
보면.. 콜백지옥.. 진짜 가독성 개 개 떨어진다. . 이런것이 콜백헬이라고 부르는 것이다.
비동기함수의 콜백함수는 언제 실행될지 정확히 예측할 수 없으므로 전역 변수에 재할당을 할 수도 없고 비동기함수의 바깥으로 콜백함수의 반환값을 반환할 수 없다. 따라서 비동기 처리 결과를 가지고 무언가를 하고 싶다면, 함수 내부에서 해야한다.
예시를 인스타그램으로 들어보자.
유저의 상세 페이지를 보고싶다면 instagram.com/유저아이디/유저고유Id 로 들어가게되고
유저의 팔로잉 목록을 보고 싶다면 instagram.com/유저아이디/유저고유Id/following/ 으로 들어가게된다.
즉 데이터를 받아오고, 그 데이터의 팔로잉을 보여주고싶다면?
const get = (url) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onload = () => {
if (xhr.status === 2000) {
return JSON.parse(xhr.response);
} else {
console.error("not found user");
}
};
};
아래에서 콜백함수로 callBack를 넣어주어 리턴하는 값에 또다른 가변을 준 것이다.
const get = (url, callBack) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onload = () => {
if (xhr.status === 2000) {
console.log(JSON.parse(xhr.response));
callBack(JSON.parse(xhr.response))
} else {
console.error("not found user");
}
};
};
그러면
get(`${url}/daeun`, userId =>{
console.log(userId)
get(`${url}/daeun/${userId}/following`, userfollowing =>{
console.log(userfollowing)
})
})
이런ㄴ ㅡ낌.. 콜백지옥..
결국 비동기 함수 내에서 콜백함수는 반환값을 내뱉지 않기 때문에 내부에서 콜백함수를 받아 가변해주는 식으로 가야한다..
get('/step/1', a=>{
get(`/step2/${a}`, b=>{
get(`/step3/${b}`, c=>{
get(`/step4/${c}`, d=>{
console.log(d)
})
})
})
})
콘노 칸지.. 거지가튼 콜백헬..