콜백 함수
: 다른 코드의 인자로 넘겨주는 함수
예제) setInterval
var count = 0;
var cbFunc = function() {
console.log(count);
if (++count > 4) clearInterval(timer);
};
var timer = setInterval(cbFunc, 300);
var intervalId = scope.setInterval(func, delay[, param1, param2, ...]);
// scope에는 Window 객체 또는 Worker의 인스턴스가 들어올 수 있음
code | 호출 주체 | 제어권 |
---|---|---|
cbFunc(); | 사용자 | 사용자 |
setInterval(cbFunc, 300); | setInterval | setInterval |
예제) Array.prototype.map
var newArr = [10, 20, 30].map(fnction (currentValue, index) {
console.log(currentValue, index);
return currentValue + 5;
});
console.log(newArr);
// 실행 결과
// 10 0
// 20 1
// 30 2
// [15, 25, 35]
Array.prototype.map(callback[, thisArg])
callback: function(currentValue, index, array)
콜백 함수는 함수이므로 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출된다.
var obj = {
vals: [1, 2, 3],
logValues: function(v, i) {
console.log(this, v, i);
}
};
obj.logValues(1, 2); // { vals: [1, 2, 3], logValues: f } 1 2
[4, 5, 6].forEach(obj.logValues); // Window {...} 4 0
// Window {...} 5 1
// Window {...} 6 2
콜백 함수 내부의 this에 다른 값 바인딩
var obj1 = {
name: 'obj1',
func: function () {
console.log(this.name);
}
};
setTimeout(obj1.func.bind(obj1), 1000);
var obj2 = { name: 'obj2' };
setTimeout(obj1.func.bind(obj2), 1500);
콜백 지옥
: 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상
: 주로 이벤트 처리나 서버 통신과 같이 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장
비동기적인 코드
: 현재 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가는 방식
콜백 지옥을 해결하며 비동기적인 작업을 하기위해 ES6에서는 Promise, Gernerator 등이 도입됐고, ES2017에서는 async/await가 도입
var addCoffee = function (name) {
return function (prevName) {
return new Promise(function (resolve) {
setTimeout(function() {
var newName = prevName ? (prevName + ', ' + name) : name;
console.log(newName);
resolve(newName);
}, 500);
});
};
};
addCoffee('에스프레소')()
.then(addCoffee('아메리카노'))
.then(addCoffee('카페모카'))
.then(addCoffee('카페라떼'))
var addCoffee = function (name) {
return new Promise(function (resolve) {
setTimeout(function() {
coffeMaker.next(prevName ? (prevName + ', ' + name) : name);
}, 500);
};
var coffeGenrator = function* () {
var espresso = yield addCoffee('', '에스프레소');
console.log(espresso);
var americano = yield addCoffee(espresso, '아메리카노');
console.log(americano);
var mocha = yield addCoffee(americano, '카페모카');
console.log(mocha);
var latte = yield addCoffee(mocha, '카페라떼');
console.log(latte);
var coffeeMaker = coffeeGenerator();
coffeMaker.next();
var addCoffee = function (name) {
return new Promise(function (resolve) {
setTimeout(function() {
resolve(name);
}, 500);
});
};
var coffeeMaker = async function () {
var coffeList = '';
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);
await _addCoffee('카페라떼');
console.log(coffeeList);
};
coffeeMaker();