안녕하세요. 개발자 J입니다.
04. 콜백 기능
4-1 콜백 함수란?
4-2 제어권
4-3 콜백 함수는 함수다
4-4 콜백 함수 내부의 this에 다른 값 바인딩하기
4-5 콜백 지옥과 비동기 제어
4-3 콜백함수는 함수다
⇒ 콜백 함수로 어떤 객체의 메서드를 전달하더라도 방법 없음 기능라고!
메소드를 콜백 함수로 전달할 때
var obj = {
vals: (1,2,3),
logValuses: function(v, i) {
console.log(this, v, i);
}
};
obj.logValues(1, 2); // 메서드로서 호출 => this : obj
// {vals: (1, 2, 3), logValues: f} 1 2
(4, 5, 6).forEach(obj.logValues); // Window { ... } 4 0 -> 5 1 -> 6 2
4-4 콜백 함수 내에서 다른 값을 바인딩합니다.
콜백 함수 내에서 다른 값을 바인딩하는 방법 → 기존 방식
var obj1={
name:'obj1',
func: function(){
var self = this;
return function(){
console.log(self.name); //this == self == obj1
};
}
};
var callback = obj1.func();
setTimeout(callback,1000); // 출력 : obj1
콜백 함수 내에서 사용하지 않는 경우
var obj1={
name: 'obj1',
func: function(){
console.log(obj1.name);
}
};
setTimeout(obj1.func,1000);
⇒ 이와 다른 상황에서 재활용 불가 (보려는 개체를 obj1로 명시적으로 지정하여)
func 함수를 재사용할 수 있습니다.
...
var obj2={
name: 'obj2',
func: obj1.func
};
var callback2 = obj2.func();
setTimeout(callback2,1500); // obj2
var obj3 = {name: 'obj3'};
var callback3 = obj1.func.call(obj3);
setTimeout(callback3, 2000); // obj3
⇒ 방법이 번거롭지만 간접적으로 사용다양한 상황에서 원하는 객체를 바라보는 콜백 함수 생성 가능
4-5 콜백 지옥과 비동기 제어
지옥을 회상하다 : 콜백함수를 익명함수에 넘기는 과정이 반복되면서 코드의 들여쓰기 수준이 참을 수 없을 정도로 깊어지는 현상.
비동기 동기
- 동기 부여적대적인 코드 : 현재 실행 중인 코드가 완료된 후오 다음 코드를 실행하는 방법
- 예) 대부분의 코드는 CPU 연산으로 즉시 처리 가능
- 비동기암호 : 현재 실행 중인 코드가 완전한지 여부에 관계없이. 다음 코드로 바로 이동
- setTimeout, addEventListener, XMLHttpRequest 등
- 별도의 요청, 실행 대기, 보류 등과 관련된 코드
지옥을 회상하다
setTimeout(function (name)){ // ---- (4)
var coffeeList = name;
console.log(coffeeList);
setTimeout(function (name)){ // ---- (3)
coffeeList += ',' + name;
console.log(coffeeList);
setTimeout(function (name)){ // ---- (2)
coffeeList += ',' + name;
console.log(coffeeList);
setTimeout(function (name)){ // ----(1)
coffeeList += ',' + name;
console.log(coffeeList);
},500,'카페라떼');
},500,'카페모카');
},500,'아메리카노');
},500,'에스프레소');
→ 0.5초마다 커피 목록을 모아서 출력하는 코드
⇒ 가독성 문제 및 어색함 수정: 모든 익명 콜백 함수 명명된 함수로 전환
콜백 지옥 해결 – 명명된 함수로 변환
var coffeeList="";
var addEsspresso = function (name) {
coffeeList = name;
console.log(coffeeList);
setTimeout(addAmericano,500,'아메리카노');
};
var addAmericano = function (name) {
coffeeList += ',' + name;
console.log(coffeeList);
setTimeout(addMocha,500,'카페모카');
};
var addMocha = function (name) {
coffeeList += ',' + name;
console.log(coffeeList);
setTimeout(addLatte,500,'카페라떼');
};
var addLatte = function (name) {
coffeeList += ',' + name;
console.log(coffeeList);;
};
setTimeout(addEspresso,500,'에스프레소');
→ 코드 가독성 ↑
자바스크립트에서 비동기 작업을 동기식으로 또는 겉보기에 동기식으로 처리⇒ 약속, 생성기, 비동기/대기 소개
비동기 작업의 동기식 표현 – 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);
});
}).then(function(prevName){
return new Promise(function (resolve){
setTimeout(function(){
var name=prevName + ', 카페라떼';
console.log(name);
resolve(name);
},500);
});
});
⇒ new 연산자로 호출된 promise의 인수로 전달된 콜백 함수는 호출 시 실행되지만 해결 또는 거부 기능다음(then) 또는 오류(catch) 문 중 하나가 실행될 때까지 진행되지 않습니다.
Asynchronous Work의 Synchronous 표현 – Promise ⇒ Iterative Content의 함수로 표현되는 Shortcode
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(prevName, name) {
setTimeout(function() {
coffeeMaker.next(prevName ? prevName + ', ' + name : name);
}, 500);
};
var coffeeGenerator = function* () { // '*'이 붙은 함수 -> Generator 함수
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();
생성기 기능을 실행할 때 이터레이터 반환 ⇒ 이터레이터는 다음 방법호출됨은 제너레이터 함수 내부에 가장 먼저 나타나는 것입니다. 생산하다에서 함수 실행을 중지합니다.
비동기 작업의 동기 표현 – Promise + Async/await
var coffee = 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로 자동 변환하고 내용이 해결된 후에만 진행합니다.