(1) 콜백 함수란?
콜백 함수는 다른 함수의 인자로 전달되어, 필요할 때 실행되는 함수입니다. 제어권을 다른 함수에게 넘기는 것이 특징입니다.
콜백 함수의 특징
- 인자로 넘겨줌: 콜백 함수는 forEach, setTimeout 등 다른 함수의 인자로 전달됩니다.
- 제어권 위임: 콜백 함수는 호출 시점과 방식이 인자를 받는 함수에 의해 결정됩니다.
- 콜백 지옥: 콜백 함수를 중첩하여 사용하면 코드의 가독성이 떨어지고 유지보수가 어려워집니다.
// setTimeout
setTimeout(function() {
console.log("Hello, world!");
}, 1000);
// forEach
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function(number) {
console.log(number);
});
제어권
콜백 함수를 넘겨받은 함수가 실행 시점과 인자를 제어합니다. 예를 들어 setInterval의 경우, 일정 시간 간격으로 콜백을 호출합니다.
var count = 0;
var timer = setInterval(function() {
console.log(count);
if(++count > 4) clearInterval(timer);
}, 300);
콜백 함수와 this
콜백 함수에서의 this는 호출 시점에 따라 달라집니다. forEach와 같은 메서드는 전역 객체를 가리킬 수 있습니다.
var obj = {
vals: [1, 2, 3],
logValues: function(v, i) {
console.log(this, v, i);
}
};
// Method로 호출
obj.logValues(1, 2);
// Callback으로 전달
[4, 5, 6].forEach(obj.logValues);
콜백 함수의 this 바인딩
콜백 함수에서 this를 바인딩하는 방법은 bind 메서드를 사용하는 것입니다.
var obj1 = {
name: 'obj1',
func: function () {
console.log(this.name);
}
};
// bind를 사용하여 obj1로 this 바인딩
setTimeout(obj1.func.bind(obj1), 1000);
var obj2 = { name: 'obj2' };
// bind를 사용하여 obj2로 this 바인딩
setTimeout(obj1.func.bind(obj2), 1500);
(2) 콜백 지옥과 비동기 제어
콜백 지옥
콜백 지옥은 비동기 작업에서 콜백을 중첩하여 사용하면서 발생하는 문제입니다. 코드의 들여쓰기 수준이 깊어지고, 가독성과 유지보수성이 떨어집니다.
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);
setTimeout(
function (name) {
coffeeList += ", " + name;
console.log(coffeeList);
},
500,
"카페라떼"
);
},
500,
"카페모카"
);
},
500,
"아메리카노"
);
},
500,
"에스프레소"
);
동기 vs 비동기
- 동기(Synchronous): 코드가 작성된 순서대로 실행됩니다. 현재 작업이 완료될 때까지 다음 작업이 대기합니다.
- 비동기(Asynchronous): 현재 작업이 완료되지 않아도 다음 작업이 실행됩니다. 예를 들어, setTimeout이나 addEventListener가 비동기적입니다.
콜백 지옥 해결 방법
콜백 지옥을 해결하기 위해 Promise, Generator, async/await 등의 비동기 제어 방법을 사용할 수 있습니다.
Promise
Promise는 비동기 작업의 결과를 처리하기 위한 객체입니다. then, catch 메서드를 사용하여 비동기 작업이 완료된 후의 동작을 정의할 수 있습니다.
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);
});
}).then(function (prevName) {
return new Promise(function (resolve) {
setTimeout(function () {
var name = prevName + ', 카페라떼';
console.log(name);
resolve(name);
}, 500);
});
});
Generator
Generator 함수는 yield 키워드를 사용하여 실행을 일시 중지하고, next 메서드 호출을 통해 실행을 재개할 수 있습니다. 비동기 작업의 진행을 제어할 수 있습니다.
var addCoffee = function (prevName, name) {
setTimeout(function () {
coffeeMaker.next(prevName ? prevName + ', ' + name : name);
}, 500);
};
var coffeeGenerator = 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();
coffeeMaker.next();
Async/Await
async/await는 비동기 코드를 동기 코드처럼 작성할 수 있게 해줍니다. await는 Promise가 해결될 때까지 실행을 일시 중지합니다.
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);
await _addCoffee('카페라떼');
console.log(coffeeList);
};
coffeeMaker();
이렇게 Promise와 async/await를 활용하면 비동기 작업을 동기적으로 작성할 수 있어 가독성을 높이고 콜백 지옥을 피할 수 있습니다.
'💻 JavaScript > 기초 문법' 카테고리의 다른 글
| ReactJS 숙련: action creators, action values, payload, Ducks 패턴 (0) | 2024.08.26 |
|---|---|
| JS 문법 종합: 콜백 함수 (0) | 2024.08.06 |
| JS 문법 종합: 실행컨텍스트(스코프, 변수, 객체, 호이스팅) (0) | 2024.07.31 |
| JS 문법 종합: 데이터 타입(심화) (1) | 2024.07.26 |
| JS 문법 종합: Map과 Set (0) | 2024.07.26 |