728x90
반응형
포스팅 주제
- 콜백(callback) 함수
- Promise
- Async / Await
비동기 처리란?
- 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행 하는 JS 특성
- 비동기 처리를 하는 이유
- 서버로 데이터 요청 시, 서버의 응답을 계속 기다리며 다음 코드를 실행 안하고 계속 기다리면 비효율 적이라
- 동기 처리시 코드 실행 -> Wait 을 반복하면 웹을 실행하는데 너무 오래 걸릴 수 있다.
콜백(CallBack)함수
콜백(CallBack)함수란?
- 이벤트가 발생했을 때 실행되는 함수(다른 함수가 실행을 끝낸 뒤 실행되는 함수)
- JS함수를 인자로 받고 다른 함수를 통해 반환될 수 있는데, 인자(매개변수)로 대입되는 함수
- 함수 선언 시 parameter(인자, 매개변수)로 함수를 받는다.
그렇다면 콜백 함수를 왜 사용할까?
- 비동기 방식로 작성된 함수를 동기 처리하기 위하여 사용한다.
- 응답을 받은 이후 처리되어야 하는 종속적인 작업이 있을 수 있으므로 그에 대한 대응이 필요하다.
// ex) 편의점에 들어가서 음료수를 사고 나오는 상황
// 콜백 함수 X
function goMart(){
console.log('마트에 와서 어떤 음료를 살지 고민중,,,')
}
function pickDrink(){
// 3초 고민(3초 후 실행)
setTimeout(function(){
console.log('좋아 골랐어!')
product = '콜라'
price = 1600;
}, 3000);
}
function pay(product, price){
console.log(`상풍명 : ${product}, 가격 : ${price}`);
}
let product, price;
goMart();
pickDrink();
pay(product, price);
위 영상을 보시면 상품명에 product와 price가 undefinde로 출력되는 것을 확인할 수 있다.
왜냐하면 지금 pickdrink함수가 setTimeout함수로 선언되어 있어서 3초뒤에 실행되기 때문에 pay함수가 인자를 못받는 것이다.
이를 해결하기 위해서는 콜백함수를 사용해서 pay가 인자를 받기 위해서 pickDrink함수가 끝나기를 기다리게 만들어줘야 한다.
// ---------콜백 함수-----------
function goMart(){
console.log('마트에 와서 어떤 음료를 살지 고민중,,,')
}
function pickDrink(callback){
// 3초 고민(3초 후 실행)
setTimeout(function(){
console.log('좋아 골랐어!')
product = '콜라'
price = 1600;
// 위에 코드가 실행된 이후 실행될 콜백함수
callback(product,price) // 매개변수로 넘긴 콜백함수 실행
}, 3000);
}
function pay(product, price){
console.log(`상풍명 : ${product}, 가격 : ${price}`);
}
let product, price;
goMart();
pickDrink(pay); //pay라는 함수를 콤백 함수로 넘겨줌
// pay(product, price);
// ------------ 콜백 함수 2 -------------
function goMart(){
console.log('마트에 와서 어떤 음료를 살지 고민중,,,')
}
function pickDrink(callback){
// 3초 고민(3초 후 실행)
setTimeout(function(){
console.log('좋아 골랐어!')
product = '콜라'
price = 1600;
// 위에 코드가 실행된 이후 실행될 콜백함수
callback(product,price) // 매개변수로 넘긴 콜백함수 실행
}, 3000);
}
function pay(product, price){
console.log(`상풍명 : ${product}, 가격 : ${price}`);
}
let product, price;
goMart();
// 직접 안에다가 함수를 만들어도 된다.
pickDrink(function pay(product, price){
console.log(`상풍명 : ${product}, 가격 : ${price}`);
});
다른 방식으로는 직접 함수를 집어 넣어도 된다.
Promise
콜백 지옥(CallBack Hell)
- 비동기 프로그래밍 시 발생하는 문제로 콜백 함수가 반복되어 코드의 들여쓰기가 너무 깊어지는 현상이다.
- 가독성이 떨어지고 코드 수정 난이도가 높아지는 단점이 있다.
이를 해결하기 위해서 Promise 형식을 사용하여 콜백 지옥을 줄일 수 있다.
Promise란?
- 비동기 함수를 동기 처리하기 위해 만들어진 객체
- 성공과 실패를 분리하여 반환
- 비동기 작업이 완료된 후 다음 작업을 연결시켜 진행하는 기능을 가진다.
Promise는 두 가지 콜백 함수를 가진다
- resolve(value): 작업이 성공(fulfilled)한 경우, 그 결과를 value와 함께 호출
- reject(error): 에러(rejected) 발생 시 에러 객체를 나타내는 error와 함께 호출
resolve()는 then 메서드로 접근(실행)가능
reject()는 catch 메서드로 접근(실행)가능
// promise(프로미스) 객체
/**
* - 비동기 함수를 동기처리하기 위해 만든 객체
* - 미래에 성공 / 실패에 대한 결과 값을 '약속' 한다는 의미
* - 성공과 실패를 분리해서 반환한다.
* - 성공에 대한 결과는 then이라는 메서드로,
* - 실패에 대한 결과는 catch라는 메서드로 처리
* - resolved : 성공
* - rejected : 실패
*/
// 1. promise 생성코드
function promise1(flag){
// 프로미스 객체를 생성하여 반환
return new Promise(function(resolved, rejected){
if(flag){
resolved(`현재 프로미스의 상태는 fulfilled(이행), then메서드로 연결! flag : ${flag}`);
}else {
rejected(`현재 프로미스의 상태는 rejected(거절), catch메서드로 연결! flag : ${flag}`);
}
})
}
// 2. promise 사용하는 코드
promise1(5 < 3).then((result) => {
console.log('result :', result);
}).catch((error) => {
console.log('error :', error);
});
// ----------- promise 예제 ------------
// index.js에서 "콜백함수"를 이용해서 동기처리한 코드를
// "promise"를 이용해 동기처리
function goMart(){
console.log('마트에 와서 어떤 음료를 살지 고민중,,,')
}
function pickDrink(){
return new Promise(function(resolved, rejected){
// 3초 고민(3초 후 실행)
setTimeout(function(){
console.log('좋아 골랐어!')
product = '콜라'
price = 2600;
const money = 2000;
if(price < money){
rejected();
} else{
resolved();
}
// resolved(); // 성공을 의미하는 resolve 실행
}, 3000);
})
}
function pay(product, price){
console.log(`상풍명 : ${product}, 가격 : ${price}`);
}
let product, price;
goMart();
pickDrink().then(() => {
pay(product, price);
}).catch(()=>{
console.log('돈이 모잘라요 ㅠㅠ');
})
프로미스(promise) 체이닝
Promise 체이닝이란?
- 여러개의 함수를 연속해서 묶어서 사용할 때 사용하는 것으로 .then을 연속으로 사용해서 사용가능
- 에러는 catch하나로 에러를 제어가능
// --------------------- 프로미스 체이닝 ----------------------
// 함수를 이용해서 (4+3)*2-1 = 13 을 연산하기!
// 1. 콜백 함수라면?
function add(n1, n2, cb){
setTimeout(function(){
const result = n1 + n2;
cb(result); // mul(result) 목적
}, 1000);
}
function mul(n, cb){
setTimeout(function(){
const result = n*2;
cb(result); // sub(result) 목적
},700);
}
function sub(n, cb){
setTimeout(function(){
const result =n - 1;
cb(result);
},500)
}
add(4,3,function(result1){
console.log('add result :', result1);
mul(result1, function(result2){
console.log('mul result :', result2);
sub(result2, function(result3){
console.log('sub result : ', result3);
})
})
})
// 2. 프로미스 체이닝이라면?
function addPromise(n1, n2){
return new Promise(function(resolv, reject){
setTimeout(function(){
const result = n1 + n2;
resolv(result);
}, 1000);
})
}
function mulPromise(n){
return new Promise(function(resolv, reject){
setTimeout(function(){
const result = n*2;
// resolv(result);
reject('의도적으로'); // 에러가 발생시 해당 문장을 출력하고 이후 중단된다.
},700);
})
}
function subPromise(n){
return new Promise(function(resolv){
setTimeout(function(){
const result =n - 1;
resolv(result);
},500)
})
}
addPromise(4,3).then(function(result1){
console.log('add result :', result1);
return mulPromise(result1);
}).then(function(result2){
console.log('mul result :', result2);
return subPromise(result2);
}).then(function(result3){
console.log('sub result :', result3);
}).catch(function(err){
console.log(err);
})
promise 체이닝을 사용하여 문장에 가독성을 올릴 수 있고, 에러 발생시 에러 문장을 출력 후 실행이 중단된다.
Promise 실습 1
// 실습1 callback -> promise
// function call(name, cb){
// setTimeout(function(){
// console.log(name);
// cb(name);
// },1000);
// }
// function back(cb){
// setTimeout(function(){
// console.log('back');
// cb('back')
// },1000)
// }
// function hell(cb){
// setTimeout(function(){
// cb("callback hell");
// },1000);
// }
// call('kim', function(name){
// console.log(name+'반가워');
// back(function(txt){
// console.log(txt+'을 실행했구나');
// hell(function(message){
// console.log('여기는'+message);
// });
// });
// });
//
function call(name){
return new Promise(function(resolve){
setTimeout(function(){
console.log(name);
resolve(name);
},1000);
})
}
function back(){
return new Promise(function(resolve){
setTimeout(function(){
console.log('back');
resolve('back')
},2000)
})
}
function hell(){
return new Promise(function(resolve){
setTimeout(function(){
resolve("callback hell");
},1000);
})
}
call('minsu').then(function(A){
console.log(A + '반가워');
return back();
}).then(function(B){
console.log(B+'을 실행했구나');
return hell();
}).then(function(C){
console.log('여기는'+ C);
})
// 화살표 함수 버전
// call('minsu').then((A) => {
// console.log(A + '반가워');
// return back();
// }).then((B) => {
// console.log(B+'을 실행했구나');
// return hell();
// }).then((C) => {
// console.log('여기는'+ C);
// })
Async / Await
Async / Await 이란?
- Promise도 체이닝을 하다보면 then.then()... 처럼 코드가 길어지고 가독성이 떨어질 수 있다.
- 가독성을 올리기 위해 Async / Await을 사용하여 Promise를 다르게 사용한다.
Async
- 함수 앞에 붙여 Promise를 반환
- 프로미스가 아닌 값을 반환해도 프로미스로 감싸서 반환
Await
- 뜻 그대로 기다리라는 기능
- 프로미스 앞에 붙여 프로미스가 다 처리될 때까지 기다리는 역할, 결과는 그 후에 반환
// async - await
// async : 함수 앞에다가 붙이는 키워드
// - 함수만 보고도 비동기 함수임을 알 수 있다.
// - 프로미스를 반환
// await : 기다린다.
// - 성공 / 실패로 프로미스 객체의 실행이 완료되기를 기다려줌
// - await 뒤에는 프로미스가 오게 됨
// async - await 짝궁, async 키워드를 사용한 함수 안에서만 await 사용가능
function goMart(){
console.log('마트에 와서 어떤 음료를 살지 고민중,,,')
}
function pickDrink(){
return new Promise((resolve, reject) => {
setTimeout(function(){
console.log('좋아 골랐어!')
product = '콜라'
price = 1600;
reject('에러 발생!!!');
// resolve();
}, 3000);
})
}
function pay(product, price){
console.log(`상풍명 : ${product}, 가격 : ${price}`);
}
// let product, price;
// async function exec(){
// goMart();
// await pickDrink();
// pay(product, price);
// }
// exec();
// async-await 키워드 사용시, 에러처리는 try-catch문으로!
async function exec1(){
try{
goMart();
await pickDrink();
pay(product, price);
}catch(error){
console.log(error);
}
}
exec1();
// then - catch를 쓰면
// goMart();
// pickDrink().then((result)=>{
// console.log(result);
// }).catch((error) => {
// console.log(error);
// })
에러 처리는 try-catch문을 사용해서 처리 가능하다.
Promise 실습 2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>콜백지옥 예시</h1>
<script>
// setTimeout(function(){
// document.body.style.backgroundColor = 'red';
// setTimeout(function(){
// document.body.style.backgroundColor = 'orange';
// setTimeout(function(){
// document.body.style.backgroundColor = 'yellow';
// setTimeout(function(){
// document.body.style.backgroundColor = 'green';
// setTimeout(function(){
// document.body.style.backgroundColor = 'blue';
// }, 1000)
// }, 1000)
// }, 1000)
// }, 1000)
// }, 1000)
</script>
<script>
function display(color){
return new Promise((resolve, reject) => {
setTimeout(() => {
document.body.style.backgroundColor = color;
resolve();
}, 1000);
});
}
// async await 방식
async function exec(){
await display('red');
await display('orange');
await display('yellow');
await display('green');
await display('blue');
}
exec();
// then 이용
// display('red').then(function(){
// return display('orange');
// }).then(function(){
// return display('yellow');
// }).then(function(){
// return display('green');
// }).then(function(){
// return display('blue');
// })
</script>
</body>
</html>
반응형
'웹 개발' 카테고리의 다른 글
[포스코X코딩온] 동적 Form 전송 (Ajax, Axios, Fetch) (3) | 2023.11.28 |
---|---|
[포스코X코딩온] 폼(Form)태그 전송(Get, Post) (0) | 2023.11.25 |
[포스코X코딩온] JS 구조분해 할당 (1) | 2023.11.23 |
[포스코X코딩온] Node.js 설치 및 모듈, Express 사용법 (2) | 2023.11.22 |
[포스코X코딩온] Bootstrap 및 Grid (0) | 2023.11.11 |