콜백함수(callback function)
라고 한다.function dessert(count, eat, good) {
count < 3 ? eatDessert() : goodDessert();
}
function eatDessert() {
console.log('오늘 먹어야 할 간식을 먹어주세요');
}
function goodDessert() {
console.log('오늘 먹어야할 간식을 모두 먹었습니다');
}
dessert(4, eatDessert, goodDessert);
dessert 함수를 호출할 때 매개변수로 count에 숫자 값을, eat과 good에 각각 eatDessert 함수와 gooddessert 함수를 전달했다. 여기서 eatDessert와 goodDessert 함수가 콜백함수(나중에 다시 불러주는 함수, 함수의 인수로 들어간 함수)인 것이다.
Javascript 기본적으로 호이스팅
이 된 이후에 순차적(동기적)으로 실행
순차적 처리하는 것이 아니라 다른 작업을 동시에 진행하고 싶으면 함수를 비동기 형태로 전환해주면 됨
그러기 위해서는 setTimeout
이라는 함수를 사용해주면 됨
setTimeout
은 일정시간 후에 특정코드, 함수를 의도적으로 지연한 뒤 실행하고 싶을 때 사용하는 함수
다음과 같은 코드에서 동기, 비동기가 무엇인지 살펴보자
console.log('1'); //동기
setTimeout(()=>console.log('2'),1000); //비동기
console.log('3'); //동기
실행 순서는 1 -> 3- > 2
두번째 줄은 비동기적으로 처리된다.
처리 순서는 동기 -> 비동기 순으로 실행된다.
callback 함수도 2가지의 경우로 정리할 수 있다.
1. synchronous callback(동기적 함수)
2. Asynchronous callback(비동기적 함수)
좀 더 긴 코드에서 동기, 비동기를 구분해보자
console.log('1');
setTimeout(function(){
console.log('2');
},1000);
console.log('3');
//동기 콜백
function printImmediately(print){
print();
}
printImmediately(()=>console.log('hello'));
//비동기 콜백
function printWithDelay(print, timeout){
setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'),2000);
실행 순서는 다음과 같다. 왜 이런 결과가 나오게 되었을까?
//동기 콜백
function printImmediately(print){
print();
}
//비동기 콜백
function printWithDelay(print, timeout){
setTimeout(print, timeout);
}
console.log('1'); //동기 1
setTimeout(function(){console.log('2');},1000); //비동기 4
console.log('3'); //동기 2
printImmediately(()=>console.log('hello')); //동기 3
printWithDelay(()=> console.log('async callback'),2000);//비동기 5
setTime
같은 함수가 있으면 비동기적으로 처리됨콜백은 나중에 다시 불러오는 함수
자바스크립트는 원래 동기적으로 실행됨
하지만 데이터를 빨리 받아오는 등 속도를 높이기 위해서 비동기적으로 바꿀 필요성이 있음
그럴 때 사용하는 것이 setTime 뒤에 몇초후에 받아올지 정해줌
동기 부터 먼저 진행
앞에서 배운 callback 함수를 여러번 중첩해서 사용한다면 Callback 지옥이라는 현상을 맛볼 수 있다. 지양해야 하는 방법이며 어떤 코드인지 살펴보고 어떤 점이 안좋은지 알아보자!
class UserStorage{
loginUser(id, password, onSuccess, onError){
setTimeout(()=>{
if(
(id==='ellie' && password ==='dream')||
(id==='coder'&& password === 'academy')
){
onSuccess(id);//id,password 일치하면 onSuccess함수에 id 인자 넘겨주기
}else{
onError(new Error('not found')); //일치하지 않으면 실패
}
},2000);
}
getRoles(user, onSuccess, onError){
setTimeout(()=>{
if(user === 'ellie'){
onSuccess({name: 'ellie', role: 'admin'}); //user가 ellie라면 onSuccess함수 이름엔ellie, 역할엔 admin 넘겨주기
}else{
onError(new Error('no access')); //아니면 no access error 반환하기
}
},1000);
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');//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`); //name값과 role 값 가져와서 알려주기
},
error => {
console.log(error); //에러반환하기
}
);
},
error=>{console.log(error)})