콜백 함수

Andy·2023년 8월 21일
0

자바스크립트

목록 보기
4/39

콜백함수는 다른 코드의 인자로 넘겨주는 함수이다.

//콜백 함수 예제-setInterval
var count=0;
var cbFunc = function(){
    console.log(count);
    if(++count>4) {
        clearInterval(timer);
    }
};
var timer= setInterval(cbFunc,1000);

timer 변수에는 setInterval의 ID값이 담깁니다. setInterval에 전달한 첫 번째 인자인 cbFunc 함수(이 함수가 콜백함수)는 1000초 마다 실행

//콜백 함수 예제-Array.prototype.map
var arr =[10,20,30].map(function(value, key){
    console.log(value, key);
    return value+5;
});
console.log(arr);

map 메서드는 첫 번째 인자로 callback 함수를 받고, 생략 가능한 두 번째 인자로 콜백 함수 내부에서 this로 인식할 대상을 특정할 수 있습니다.

콜백 함수는 함수다.

콜백 함수로 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출한다.

var obj={
    vals:[1,2,3],
    logValues: function(v,k){
        console.log(this,v,k); 
    }
};
obj.logValues(1,2); //obj객체를 this로 명시함
[4,5,6].forEach(obj.logValues); //전역 객체를 this로 명시함

콜백 함수 내부의 this에 다른값 바인딩하기

//this를 다른 변수에 담기
var obj={
    func: function(){
        var self=this;
        return function(){
        console.log(self); //obj객체를 this로 명시함
    }
}
};
var callback=obj.func();
setTimeout(callback,1000);
//func 함수 재활용
var obj={
    name: 'obj',
    func: function(){
        var self=this;
        return function(){
            console.log(self.time);
        };
    },
    time: '1000',
};
var callback=obj.func();
setTimeout(callback, 1000);
var obj2 ={
    name: 'obj2',
    func: obj.func,
    time: '1500'
};
var callback2=obj2.func(); 
setTimeout(callback2,1500);
var obj3={
    name: 'obj3',
    time:'2000',
}
var callback3 = obj.func.call(obj3);
setTimeout(callback3,2000);
//bind 메서드 활용
var obj={
    name: 'obj',
    func: function(){
        console.log(this.time);
    },
    time: '1000',
}
setTimeout(obj.func.bind(obj),1000);
var obj2={
    name: 'obj2',
    time: '2000',
}
setTimeout(obj.func.bind(obj2),2000);

콜백 지옥과 비동기 제어

//콜백 지옥 예시
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);
            },1000,'카페라떼')
        },1000,'카페 모카')
    },1000, '아메리카노')
},1000,'에스프레소')

가독성의 문제를 해결해주는 방법은 익명의 콜백함수를 모두 기명함수로 바꾸는 것!

//기명 함수로 변환
var coffeeList = '';
var espresso= function(name){
    coffeeList = name;
    console.log(coffeeList);
    setTimeout(americano,1000,'아메리카노');
}
var americano =function(name){
    coffeeList +=name;
    console.log(coffeeList);
    setTimeout(caffeLatte,1000, '카페라떼');
}
var caffeLatte = function(name){
    coffeeList+= name;
    console.log(coffeeList);
    setTimeout(caffeMocha,1000,'카페모카')
}
var caffeMocha = function(name){
    coffeeList+=name;
    console.log(coffeeList);
};
setTimeout(espresso,1000,'에스프레소');

ES6에서의 promise 도입

//비동기 작업의 동기적 표현(1)-promise문
new Promise(function(resolve){
    setTimeout(function(){
        var name='에스프레소';
        console.log(name);
        resolve(name);
    },1000);
}).then(function(prevName){
    return new Promise(function(resolve){
        setTimeout(function(){
            var name= prevName+'아메리카노';
            console.log(name);
            resolve(name);
        },1000);
    });
}).then(function(prevName){
    return new Promise(function(resolve){
        setTimeout(function(){
            var name=prevName+'카페 라떼';
            console.log(name);
            resolve(name);
        },1000);
    });
}).then(function(prevName){
    return new Promise(function(resolve){
        setTimeout(function(){
            var name= prevName+'카페 모카';
            console.log(name);
            resolve(name);
        },1000);
    });
});

❗️new 연산자와 함께 호출한 promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만, 그 내부에 resolve 또는 reject함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 다음(then) 또는 오류 구문(catch)으로 넘어가지 않습니다.
따라서 비동기 작업이 완료될 때 비로소 resolve 또는 reject를 호출하는 방법으로 비동기 작업의 동기적 표현이 가능합니다.
아래의 코드는 반복적인 내용을 함수화해서 더욱 짧게 표현한 것

//비동기 작업의 동기적 표현(2)-promise
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);
            },1000);
        });
    };
};
addCoffee('에스프레소')()
    .then(addCoffee('아메리카노'))
    .then(addCoffee('카페모카'))
    .then(addCoffee('카페라떼'));

ES6에서의 generator도입

//비동기 작업의 동기적 표현(3)-Generator
var addCoffee = function(prevName, name){
    setTimeout(function(){
        coffeeMaker.next(prevName? prevName+','+name:name);
    },1000);
}; 
var coffeeGeneraotr= 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 = coffeeGeneraotr();
coffeeMaker.next();

❗️*이 붙은 함수가 바로 generator 함수이다. generator 함수를 실행하면 iterator가 반환되는데, iterator는 next라는 메서드를 가지고 있다. 이 next 메서드를 호출하면 generator 함수 내부에서 가장 먼저 등장하는 yield에서 함수의 실행을 멈춤. 이후 다시 next메서드를 호출하면 앞서 멈췄던 부분부터 시작해서 그다음에 등장하는 yield에서 함수의 실행을 멈춤.

ES2017에서의 async/await 도입

비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고, 함수 내부에서 실징적인 비동기 작업이 필요한 위치마다 await를 표기하는 것만으로 뒤의 내용을 promise로 자동 전환하고, 해당 내용이 resolve된 이후에야 다음으로 진행

var addCoffee = function(name){
    return new Promise(function(resolve){
        setTimeout(function(){
            resolve(name);
        },1000);
    });
};
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();
profile
열정으로 가득 찬 개발자 꿈나무 입니다

0개의 댓글