sitelink1 | https://blog.naver.com/ksyooon0718/222218782502 |
---|---|
sitelink2 | |
sitelink3 | |
sitelink4 | |
extra_vars4 | |
extra_vars5 | |
extra_vars6 |
* 내용 스크랩
05. 콜백지옥과 비동기제어
- 콜백지옥은 콜백함수를 익명함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 깊어지는 현상
- 주로 이벤트처리나 서버 통신과 같이 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장함
- 동기적인 코드는 현재 실행중인 코드가 완료된 후에야 다음 코드를 실행하는 방식
- 비동기적인 코드는 현재 실행중인 코드 완료 여부와 무관하게 즉시 다음 코드로 넘어감
- 사용자의 요청에 의해 특정 시간이 경과되기 전까지 어떤 함수의 실행을 보류한다거나(setTimeout)
- 사용자의 직접적인 개입이 있을 때 함수를 실행하도록 대기한다거나 (addEventListener)
- 웹브라우저 자체가 아닌 별도의 대상에 무언가를 요청하고 응답이 왔을 때 함수를 실행하도록 대기하는 (XMLGttpRequest)
- 이런 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 비동기적인 코드
// setTimeout 문법
var timeoutID = window.setTimeout(func[, delay, param1, param2, ...]);
var timeoutID = window.setTimeout(code[, delay]);
window.setTimeout(function, milliseconds);
// 예제 4-12
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,'에스프레소');
// 에스프레소
// 에스프레소, 아메리카노
// 에스프레소, 아메리카노, 카페모카
// 에스프레소, 아메리카노, 카페모카, 카페라떼
// 문제점 : 들여쓰기 수준이 깊어졌으며, 값이 전달되는 순서가 아래에서 위로 향하고 있어 어색하게 느껴짐
// 예제 4-13 - 기명함수로 변환
var coffeeList = '';
var addEspresso = 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, '에스프레소');
// 가독성은 좋아졌지만, 일회성 함수라는 것이 단점
- setTimeout을 변수에 넣는 과정에서 메서드가 실행된다고 배웠는데, 위 예제에서 실행되지 않는 이유
=> setTimeout을 함수안에 넣었기 때문에 함수를 실행하지 않는 이상 별도로 실행되지 않는다
// 예제 4-14 비동기 작업의 동기적 표현 - 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);
});
- resolve 또는 reject 함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 then 또는 오류구문(catch)으로 넘어가지 않음
// 예제 4-15 비동기작업의 동기적 표현 - Promise2
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('에스프레소')() // 함수 addCoffee 안에 return값으로 내부함수가 있는구조기 때문에 함수 실행을 두번한다
.then(addCoffee('아메리카노'))
.then(addCoffee('카페모카'))
.then(addCoffee('카페라떼'));
- 함수 addCoffee안에 return값으로 내부함수가 있는 구조기 때문에 함수 실행을 두번한다
- 이후 then의 두번째 함수의 인자로 이전 resolve값이 온다
// 예제 4-16 비동기작업의 동기적표현 - Generator
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();
- '*'이 붙은 함수가 Generator 함수
- 함수 실행시 Iterator가 반환되는데, Iterator는 next라는 메서드를 가지고 있음
- next메서드 호출시 가장 먼저 등장하는 yield에서 함수의 실행을 멈춤
- 이후 다시 next메서드를 호출하면 앞서 멈췄던 부분부터 시작해서 다음에 등장하는 yield에서 함수의 실행을 멈춤
// 비동기작업의 동기적표현 - Promise+Async/await
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();
- 비동기 작업을 수행하고자 하는 함수 앞에 async를 표기한다,
- 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await 표기하는 것만으로 뒤의 내용을 Promise로 자동전환되며,
해당 내용이 resolve된 이후에야 다음으로 진행된다 ( Promise then과 흡사한 효과를 얻을 수 있다 )
