1. 콜백 함수란?
콜백 함수는 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 말한다. 함수안에서 실행되는 또다른 함수라고 할 수 있다. JS에서 함수는 일급객체이기 때문에 다른 함수의 매개변수로 등록할 수 있다.
function repeat(n, f) {
for (var i = 0; i < n; i++) {
f(i); // i를 전달하면서 f를 호출
}
}
// callback으로 등록될 함수
const logAll = function (i) {
console.log(i);
};
repeat(5, logAll); // 0 1 2 3 4
2. 콜백 함수의 사용
⓵ 내장 매서드
const nums = [1, 2, 3, 4, 5, 6];
const result = nums.filter(num => num > 3);
// 조건을 만족하는 요소를 추출해 새로운 배열 리턴
console.log(result); // [4, 5, 6]
const initialValue = 0;
const sum = nums.reduce(
(accumulator, currentValue) => accumulator + currentValue, initialValue
);
// 배열 내 모든 수를 더하는 콜백함수를 사용, accumulator를 return 한다.
console.log(sum);
⓶ 고차 함수
고차 함수란 외부에서 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 말한다.
const nums = [1, 2, 3, 4, 5, 6];
// filter 매서드를 직접 만들어보자
function myfilter(array, callback){
let result = [];
for(let i=0; i<array.length; i++){
let current = array[i];
if(callback(current)){
result.push(current)
}
}
return result;
}
const newArr = myfilter(nums, num => num > 3);
console.log(newArr); // [4,5,6]
⓷ 이벤트 처리
// 콜백으로 등록될 함수
function onClick1() {
alert(' clicked!');
}
// addEventListener의 두번째 인자로 콜백 함수를 등록한다.
document.getElementById('clickMe').addEventListener('click', onClick1);
⓸ 비동기 처리
비동기 함수를 사용하는 경우 예상과는 다르게 결과가 나오는 경우가 있다.
function findUser(id) {
let user;
setTimeout(function () {
console.log("wait 1 sec.");
user = `${id}`;
}, 1000);
return user;
}
const user = findUser('kim');
console.log("user :", user);
// 실행 결과 user : undefined
// wait 1 sec.
콜백 함수를 이용하면 이러한 비동기 처리를 제대로 할 수 있다.
function findUserAndCallBack(id, cb) {
setTimeout(function () {
console.log("wait 1 sec.");
const user = `${id}`;
cb(user);
}, 1000);
}
findUserAndCallBack("kim", function (user) {
console.log("user:", user);
});
// 실행 결과 wait 1 sec.
// user:kim
3. 콜백 함수의 장점과 단점
장점
⓵ 함수 외부에서 주입하기 때문에 자유로운 교체가 가능하다. (코드의 가변성이 높아진다.)
⓶ 함수를 굳이 정의하지 않고 익명 함수로도 전달 가능하다.(메모리 측면에서 유리)
⓷ 비동기(Asynchronous) 처리 방식의 문제점을 해결할 수 있다.
단점
⓵ 콜백 함수를 너무 남용하면 코드의 가독성이 떨어진다.(콜백 지옥)
⓶ 에러 처리가 어렵다.
4. 콜백 함수 사용시 주의사항
⓵ 인자로 넘길때 소괄호 넣으면 안된다.
⓶ this를 보호할 수 있도록 콜백함수를 만들어야 한다. (call, apply 등을 통해 보호)
const user = {
name: null,
setName : function(name){
this.name = name
}
}
// apply 사용 예제 apply() : 첫 번째 인자로 this 객체 사용, 나머지 인자들은 배열 형태로 전달
function setUserName(name,callback,thisObj){
callback.apply(thisObj,[name])
}
setUserName('IU',user.setName,user)
console.log(user.name) //'IU'
//call 사용 예제 call() : 첫 번째 인자로 this 객체 사용, 나머지 인자들은 , 로 구분
function setUserName(name,callback,thisObj){
callback.call(thisObj,name)
}
setUserName('IU',user.setName,user)
console.log(user.name) //'IU'
⓷ 콜백 지옥에 빠지지 않도록 해야한다.( 주로 비동기 처리에서 발생한다.)
function randomTime() {
return Math.floor(Math.random() * 10) * 1000;
}
function errorFunction() {
console.log('재고가 없습니다.');
}
function getChicken(callback, errorFunction) {
if (callback) {
setTimeout(() => {
console.log('동묘시장 -> chicken');
callback();
}, randomTime());
} else {
errorFunction();
}
}
function getEgg(callback, errorFunction) {
if (callback) {
setTimeout(() => {
console.log(`동묘시장 -> chicken -> egg`);
callback();
}, randomTime());
} else {
errorFunction();
}
}
function getMeal(callback, errorFunction) {
if (callback) {
setTimeout(() => {
console.log(`동묘시장 -> chicken -> egg -> fried egg`);
callback();
}, randomTime());
} else {
errorFunction();
}
}
getChicken(() => {
getEgg(() => {
getMeal(() => {}, errorFunction);
}, errorFunction);
}, errorFunction);
ES6에서 추가된 promise, ES2017에서 추가된 async/await을 이용하면 콜백 지옥을 예방할 수 있다.
function randomTime() {
return Math.floor(Math.random() * 10) * 1000;
}
function errorFunction() {
console.log('재고가 없습니다.');
}
function getChicken() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('동묘시장 -> chicken');
resolve(getEgg);
}, randomTime());
});
}
function getEgg() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('동묘시장 -> chicken -> egg');
resolve(getMeal);
}, randomTime());
});
}
function getMeal() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('동묘시장 -> chicken -> egg -> fried egg');
}, randomTime());
});
}
getChicken()
.then((data) => data())
.then((data) => data())
.then((data) => console.log(data));
Reference
- https://kong-dev.tistory.com/120
- https://im-designloper.tistory.com/26
- https://www.daleseo.com/js-async-callback/
- https://www.youtube.com/watch?v=TAyLeIj1hMc&t=6s
'내맘대로 개념정리' 카테고리의 다른 글
| Javascript Class로 배열 만들어보기 (0) | 2023.10.13 |
|---|---|
| 객체지향 프로그래밍과 함수형 프로그래밍 (0) | 2023.01.13 |
| XML 과 JSON (1) | 2023.01.03 |
| 계산기 CSS 정리 (0) | 2022.12.29 |
| Typescript를 사용하는 이유는 무엇일까? (0) | 2022.12.24 |
댓글