콜백 함수는 다른 코드의 인자로 넘겨주는 함수다.
어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출하게끔 하는것인데 이렇듯 제어권을 다른 코드를 넘겨준것이 콜백함수이다.
대표적인 예시로 setInterval, map등의 함수등이 있다.
var count = 0;
var callbackFunc = function(){
console.log(count);
if(++count > 4) clearInterval(timer);
}
var timer = setInterval(callbackFunc, 400);
// 0, 1, 2, 3, 4 를 0.3초 간격으로 호출함
이처럼 콜백 함수의 제어권을 넘겨받은 코드는 콜백함수 호출 시점에 대한 제어권을 가진다.
콜백 함수를 사용하는 이유는 비동기적인 프로그래밍을 할 수 있기 때문이다.
프로그래밍을 하다보면 이벤트의 처리라든가, 시간 지연, 네트워크 응답등의 처리를 해야 되는 때가 있다.
만약 서버로부터 이미지를 20개 불러오는 해야 될때 20개의 이미지를 불러오는 동안 다른 코드들은 실행하지 않고 있는다면 언제 올지도 모를 이미지때문에 다른 코드들을 실행하지 못하고 기다려야 한다. 이런 이유 때문에 우리는 비동기 처리를 위해 콜백함수를 사용해야 한다.
콜백함수를 공부하면서 느낀건데 콜백함수는 결국 함수다.
저번에 공부할때 자바스크립트에서 this가 바라보는 방향을 알아보는 방법중에 메서드로써 사용중일때에는 사용중인 프로퍼티의 객체를 바라보게끔 되어있지만,
콜백함수 방식으로 메서드를 사용할경우엔 메서드가 아닌 함수로써 작동하기 때문에 this를 따로 지정해주지 않은 이상 this는 전역객체를 바라보게된다.
var obj = {
vals: [1, 2, 3],
logValues: function(v, i){
console.log(this, v, i)
}
}
obj.logValues(1, 2) // obj{}, 1, 2
[4, 5, 6].forEach(obj.logValues)
// window{}, 4 0
// window{}, 5 1
// window{}, 6 2
콜백지옥이라는 말을 많이 들어봤을 것이다.
자바스크립트에서 비동기 처리를 해줄때에 콜백함수를 연달아 사용하다보면 가독성과 변수명등이 헷갈리는 경우가 있어서 겪는 고통을 콜백지옥이라고 하는데 예시와 그 해결법인 promise와 가장 최근에나온 async/await 까지 한 번에 보면서 비교해보자
setTimeout(function(name){
var coffeeList = name;
console.log(coffeeList);
setTimeout(function (name){
coffeeList += ', ' + name;
console.log(coffeeList);
setTimeout(function (name){
coffeeList += ', ' + name;
console.log(coffeeList);
}, 500, '아메리카노')
}, 500, '국밥')
}, 500, '프라푸치노')
3줄만 적어도 어질어질 하다. 이런 방식은 들여쓰기 때문에 가독성도 떨어지고 무엇부터 출력이 되는지도 바로 알아보기 힘들뿐더러 작성효율면에서 좋지 않다.
이를 보완하기 위해서 나온 promise 를 보자
new Promise(function (resolve){
setTimeout(function(){
var name = '프라푸치노';
console.log(name);
resolve(name);
}, 500);
}).then(function(prevName){
return new Promise(function(resolve){
setTimeout(function(){
var name = prevName + ', 국밥';
console.log(name);
resolve(name);
}, 500);
})
}).then(function(prevName){
return new Promise(function(resolve){
setTimeout(function(){
var name = prevName + ', 아메리카노';
console.log(name);
resolve(name);
}, 500);
})
})
Promise 함수를 사용하여 들여쓰기로 인한 불편함이 해소됐다.
다음은 가장 최근에 나온 async/await을 사용한 방법을 살펴보자
var addCoffee = function(name){
return new Promise(function(resolve){
setTimeout(function(){
resolve(name)
},500)
})
}
var coffeeMaker = async function(){
var coffeeList = '';
var _addCoffee = async function(name){
coffeeList += (coffeeList ? ',' : '') + await addCoffee(name);
}
await _addCoffee('프라푸치노');
console.log(coffeeList);
await _addCoffee('국밥');
console.log(coffeeList);
await _addCoffee('아메리카노');
console.log(coffeeList);
}