1. 콜백지옥
function do () {
$.get(url, function (result) {
setTimeout(function () {
startAsyncProcess(function (){
...
}
}, 1000)
}
}
연속된 이벤트나 서버통신같은 비동기적 작업을 수행할 때 이러한 콜백함수 지옥에 빠지곤한다.
이렇게 연속된 콜백함수는 코드의 유지보수를 어렵게하며, 다른사람이나 미래의 내가 코드를 봤을 때 이해하기 어렵게 만든다.
2. 동기 vs 비동기
동기 (Sync) - 카페에서 줄을서서 주문을 하는데, 주문을 하고 커피가 손님에게 전달될때까지 다음 주문으로 넘어가지 않는다.
비동기 (Async) - 카페에서 줄을 서서 주문을 하는데, 주문을 하면 진동벨을 받고 자리에 이동하여 다음 주문을 받는다.
1. 동기 synchronous
- 현재 실행중인 코드가 끝나야 다음 코드를 실행하는 방식
- CPU의 계산에 의해 즉시 처리가 가능한 대부분의 코드는 동기적 코드이다.
- 계산이 복잡해서 오래걸리는 코드도 동기적 코드이다.
2. 비동기 asyncronous
- 실행중인 코드의 완료여부와 무관하게 즉시 다음 코드로 넘어가는 방식
- setTimeout, addEventListener 등
- 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 모두 비동기적 코드
// 비동기적 코드의 이해
setTimeout(() => {
console.log("여기가 먼저 실행될까?");
}, 1000);
console.log("여기좀 봐주세요!!!");
1초를 기다린 뒤 "여기가 먼저 실행될까?"가 먼저 출력되고 "여기좀 봐주세요!!!"가 출력될 것 같지만, setTimeout은 비동기적 코드이기 때문에 "여기좀 봐주세요!!!"가 먼저나오고 약 1초를 기다린 뒤 "여기가 먼저 실행될까?"가 출력된다.
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,
"에스프레소"
);
setTimeout을 이용하여 여러 카페음료를 console.log하는 것이다. 콜백지옥이다.
작동 순서도 헷갈리고 이해하는데에도 시간이 걸린다.
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으로 넣은 방식이다.
훨씬 깔끔하지만, 거의 비슷한 기능의 함수를 4개를 만들어 사용하여 효율적이지 못하다.
비동기 작업 => 순서를 보장하지 못한다.
따라서 비동기 작업을 동기적으로 표현하여 오류를 방지해야한다.
Promise는 비동기 처리에 대하여, 처리가 끝나면 알려달라는 '약속'이다.
- new 연산자로 호출한 Promise의 인자로 넘어가는 콜백은 바로 실행된다.
- 그 내부의 resolve(또는 reject) 함수를 호출하는 구문이 있을 경우 resolve, reject 둘 중 하나가 실행되기 전까지는 then, catch로 넘어가지 않는다.
- 따라서, 비동기 작업이 완료될 때 비로소 resolve, reject를 호출한다.
new Promise(function (resolve) {
setTimeout(function () {
var name = "에스프레소";
console.log(name);
resolve(name);
}, 500);
})
.then(function (prevName) {
//안에서 새롭게 Promise를 만든다.
return new Promise(function (resolve) {
setTimeout(function () {
var name = prevName + ", 아메리카노";
console.log(name);
resolve(name);
}, 500);
});
})
.then(function (prevName) {
//안에서 새롭게 Promise를 만든다.
return new Promise(function (resolve) {
setTimeout(function () {
var name = prevName + ", 카페모카";
console.log(name);
resolve(name);
}, 500);
});
})
.then(function (prevName) {
//안에서 새롭게 Promise를 만든다.
return new Promise(function (resolve) {
setTimeout(function () {
var name = prevName + ", 카페라떼";
console.log(name);
resolve(name);
}, 500);
});
});
위에서 카페음료를 출력하는것을 promise로 바꾼 것이다.
var addCoffee = function (name) {
return function (prevName) {
//안에서 새롭게 Promise를 만든다.
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("카페라떼"));
중첩함수를 이용하여 처음과 그 이후를 구분했다.
처음 함수가 실행될 때에는 addCoffee('에스프레소)로 return된 function (prevName)을 즉시 실행하여 prevName이 없으므로 name만 newName에 들어가 resolve되고,
그 후로는 addCoffee('아메리카노')가 실행되어 prevName에는 resolve로 전해진 '에스프레소'가 들어있어
newName = '에스프레소, 아메리카노'가 된다. 또 newName을 resolve하는 것으로 반복하여 마지막 addCoffee('카페라떼')까지 실행되면
"에스프레소, 아메리카노, 카페모카, 카페라떼"가 출력된다
'2차 공부 > TIL' 카테고리의 다른 글
24.07.25 클래스 (0) | 2024.07.25 |
---|---|
24.07.25 DOM / DOM 조작하기 (0) | 2024.07.25 |
24.07.23 This (0) | 2024.07.23 |
24.07.23 콜/스택, 실행 컨텍스트 (0) | 2024.07.23 |
24.07.23 변수선언과 데이터 할당 / 불변하다 vs 불변하지 않다. (0) | 2024.07.23 |