DEVLOG
동기방식 vs 비동기방식, 콜백함수와 Promise 까지 한번에 훑어보기! 본문
데이터 처리 모델의 방식 :: 동기방식 vs 비동기방식
동기방식
순차적으로 동작하는 방식
요청을 보낸 후 해당 응답을 받아야 다음 동작을 실행하며 이 동작이 끝날때까지 다음 동작은 대기상태이다.
위 그럼 a처럼 카페에서 줄을 서서 커피를 받는 방식으로 비유하는데,
한 동작이 끝날때까지 기다리기 때문에 동작이 느리다는 느낌을 받을 수 있다.
이것은 실제 CPU가 느려지는 것은 아니지만 시스템 전체적인 효율이 저하된다고 볼 수 있다.
설계가 간단하고 직관적이라는 장점을 가지지만, 결과를 볼 때까지 아무것도 못하고 대기해야 한다는 단점이 있다!
function func1(){
console.log("1번입니다");
func2();
}
function func2(){
console.log("2번입니다");
func3();
}
function func3(){
console.log("3번입니다");
}
func1();
//1번입니다
//2번입니다
//3번입니다
비동기방식
순차적으로 진행하지 않는 방식
요청을 보내고 응답에 관계없이 바로 다음 동작을 실행한다.
동기보다 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있는 장점이 있다.
why need?
클라이언트에서 서버로 데이터를 요청 했을 때, 서버가 그 요청에 대한 응답을 언제 줄지도 모르는데 데이터가 다 받아질때까지 앱이 대기상태로 머물러있을 수 없기 때문에 비동기방식이 필요하다.
* 자바스크립트에서 비동기방식이 가능한 이유
자바스크립트는 흔히 알고있듯 싱글스레드로 프로그램이 동작한다.
**싱글스레드**
한 번에 한가지 일만 처리가 가능한 단일 스레드
그런데 동시의 여러 작업이 동작되는 비동기방식은 멀티태스킹 작업일 수 밖에 없는데 어떻게 자바스크립트에서 비동기방식이 가능한걸까?
자바스크립트는 웹 브라우저나 Node.js의 자바스크립트 엔진에서 실행이 된다.
이 엔진에는 자바스크립트를 돌리는 하나의 스레드가 존재한다.
또한 이 엔진 뿐만 아니라 자바스크립트 엔진은 Web API를 두었고, 비동기식 처리 모델인 Web API라는 것이 함께 동작하면서 여기에서 setTimeout이나 Ajax등 기다리는 시간이 필요한 일들을 처리한다.
이 Web API들이 자바스크립트 엔진 스레드와는 따로 비동기 처리를 따로 돌면서 콜백함수를 가지고 이벤트 루프에 들어가 처리되는대로 콜백함수를 다시 자바스크립트 엔진으로 돌려보내준다.
example
setTimeout, ajax ...
setTimeout
function func1(){
console.log("1번입니다");
func2();
}
function func2(){
setTimeout(
console.log("2번입니다");
, 3000
);
func3();
}
function func3(){
console.log("3번입니다");
}
func1();
//1번입니다
//3번입니다
//2번입니다
ajax
function getData() {
var tableData;
$.get('url', function (response) {
tableData = response;
}) // $.get()로 데이터를 요청하고 받아올 때까지 기다리지 않고 return 해버림
return tableData;
}
console.log(tableData) // 따라서 undefined
이때, 비동기방식의 문제점을 확인할 수 있다.
비동기방식의 문제점
바로 데이터통신이 되기도 전에 값을 return해버리게 되거나 이 값을 이용하는 어떠한 동작이 동시에 이루어질 경우 undefined값을 사용할 수 밖에 없다.
How can I do?
콜백함수를 이용하자!
콜백함수
콜백함수란?
- 다른 함수의 인자로서 이용되는 함수
- 어떤 이벤트에 의해 호출되는 함수
callback은 쉽게 말하자면 어떤 일을 다른 객체에게 시키고, 그 일이 끝나는 것은 기다리지 않고 끝나고 부를 때까지 다른 일을 하는 것을 말한다.
function plus(x, y, callback) {
sum = x + y;
callback(sum)
}
function print(result) {
console.log(result);
}
plus( 1, 2, print);
동작순서
- plus함수가 실행된다.
- plus함수의 매개변수인 1과 2의 연산값이 sum으로 들어간다.
- 매개변수인 callback에 들어간 콜백함수인 print가 callback에 들어간다.
- print함수가 실행된다.
- print함수의 인자로 사용된 sum이 console.log에 들어감
- 콘솔에 3이 나옴.
function increase(number, callback){
setTimeout(()=>{
const result=number+10;
if(callback){
callback(result);
}
},1000)
}
increase(0, result=>{
console.log(result);
});
콜백함수 중첩
1초 뒤 result에 10을 더해서 반환하는 함수를 예로 들어볼때 1초에 걸쳐서 10, 20, 30, 40 과 같은 형태로 여러번 반복을 하고 싶을때 콜백함수를 중첩하여 다음과 같이 구현할 수 있다.
function increase(number,callback){
setTimeout(()=>{
constresult=number+10;
if(callback){
callback(result);
}
},1000);
}
console.log('작업시작');
increase(0,result=>{
console.log(result);
increase(result, result=>{
console.log(result);
increase(result,result=>{
console.log(result);
increase(result,result=>{
console.log(result);
console.log('작업완료');
});
});
});
});
네! 이런 코드를 콜백지옥이라고 합니다!
콜백지옥
콜백, 콜백, 콜백의 반복으로 depth가 깊어지는 코드를 콜백지옥이라고 부른다
이러한 코드는 가독성을 매우 떨어뜨리므로 지양해야한다.
// 콜백지옥, 가독성이 떨어짐
$.get('url', function (response) {
parseValue(response, fuction(id) {
auth(id, function (result) {
display(result, function (text) {
console.log(text)
})
})
})
})
Promise
콜백지옥 같은 코드를 해결하는 방안으로 ES6에 도입된 기능이다 (IE안녕..)
promise 객체를 사용하여 비동기 작업이 완료된 후(성공 혹은 실패) 결과값을 받을 수 있어 이후 처리를 쉽게 컨트롤할 수 있다.
Promise는 함수를 인자로 받으며 인자로 들어온 함수는 다시 resolve(비동기 처리 성공)와 reject(비동기 처리 실패) 2개의 함수를 인자로 받게 된다.
resolve 시 then 메소드, reject 시 catch 메소드의 인자로 넘어간다.
function increase(number){
const promise=newPromise((resolve,reject)=>{
// resolve는성공, reject는실패
setTimeout(()=>{
const result=number+10;
if(result>50){
// 50보다높으면에러발생시키기
const e=newError('NumberTooBig');
return reject(e);
}
resolve(result);// number값에 +10후성공처리
},1000);
});
return promise;
}
increase(0).then(number=>{
// Promise에서 resolve된값은 .then을통해받아올수있음
console.log(number);
return increase(number);
// Promise를리턴하면
})
.then(number=>{
//또 .then으로처리가능
console.log(number);
return increase(number);
})
.then(number=>{
console.log(number);
return increase(number);
})
.then(number=>{
console.log(number);
return increase(number);
})
.then(number=>{
console.log(number);
return increase(number);
})
.catch(e=>{//도중에에러가발생한다면 .catch를통해알수있음
console.log(e);
});
'frontend > javascript' 카테고리의 다른 글
[Javascript] 현재 스크롤값 확인하기 :: pageYOffset, scrollY (0) | 2021.06.21 |
---|---|
[Javascript] var, let, const 의 차이점 (0) | 2021.05.03 |
[Javascript] 삼항연산자 (0) | 2021.03.29 |
[Javascript] 남은시간 카운트다운 만들기 (0) | 2021.03.09 |
[Javascript/jQuery] 숫자가 0부터 증가하는 애니메이션 넣기 (0) | 2021.03.09 |