1,2,3,4 순서에 따라 처리되는것이 아닌 먼저 처리된 코드를 우선순위를 두고 실행시켜주는 코드.
비동기 함수의 종류에는 콜백함수,promise함수,async,await 함수가 있다.
함수자체를 인자로 전달하는 함수를 의미
settimeout함수로 함수를 전달하면 그것도 콜백
//비동기식 프로그래밍 1->3->2 순으로 콘솔에 찍힌다.
console.log('1')
setTimeout(function() {
console.log('2')
},1000)
console.log('3')
쉽게 말하자면 콜백함수는 말그대로 호출용이고
(인자 전달 및 callback호출용도) 내부에 함수 실행 코드는 없다. 콜백함수랑 같이 쓰일 함수가 더 있어야한다(함수 실행 코드).
function first(callback){
setTimeout(() => {
console.log("10초 뒤 실행");
callback();
}, 10000);
}
function second(){
console.log("저는 first다음으로 실행해주세요~~");
}
first(second);
이 함수는 일반적인 callback의 유형이다. 대신 first가 실행되기전에 second는 손가락만 쪽쪽 빨고있어야한다. 이유는 first안에 second로 매개변수를 던져서 first에 제어권한이 있기 때문이다. 즉 second가 이미 준비 완료가 되어있어도 first가 준비되기 전까지는 호출이 되어지지 않는다는 뜻이다.
ex ) 매표소 -> 매표소에서 표를 사려고 지갑을 꺼내서 맞는 금액을 손에 쥐고있어도 당신은 바로 살수가 없다. 그앞에있는 사람이 존재하기 때문이다.
callback을 안쓴 동기함수 버전
function func1(){
console.log("1번입니다");
func2();
}
function func2(){
console.log("2번입니다");
func3();
}
function func3(){
console.log("3번입니다");
}
func1();
//1번입니다
//2번입니다
//3번입니다
다음은 callback을 사용하지 않은 비동기 함수의 예시다.
function func1(){
console.log("1번입니다");
func2();
}
function func2(){
setTimeout(
console.log("2번입니다");
, 3000
);
func3();
}
function func3(){
console.log("3번입니다");
}
func1();
//1번입니다
//3번입니다
//2번입니다
정리 : func1은 2를 호출하면서 먼저 실행되는 함수고 func2는 시간차가 있는 즉 비동기적 함수고 func3는 2에서 호출되는 함수지만 func2의 시간차를 고려해 func2보다 먼저 실행되었다
1-1 비동기방식의 문제점
바로 데이터통신이 되기도 전에 값을 return해버리게 되거나 이 값을 이용하는 어떠한 동작이 동시에 이루어질 경우 undefined값을 사용할 수 밖에 없다.
1-2 콜백지옥 (계단식 논) => 가독성 구려,실제로 데이터가 전달되지 않는 채로 호출될 상황 발생 가능성
function Callback(callback){
function Callback2(callback){
function Callback3(callback){
console.log('무한콜백');
}
}
}
Promise의 세가지 상태(States)
Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
Pending 상태 예시
아래와 같이 Promise 객체를 생성하는 시점부터 Pending상태이다.
또한 콜백함수의 인자로서 resolve,reject를 받을 수 있다.
new Promise(function(resolve, reject) {
});
Fulfilled(이행) : 비동기 처리 로직이 수행완료되어 결과 값을 반환한 상태
new Promise(function(resolve, reject) {
resolve();
});
Rejected(실패) : 비동기 처리가 실패하거나 에러가 발생한 상태
new Promise(function(resolve, reject) {
rejected();
});
아래는 동기 방식 코드다.
new Promise((r1, r2) => {
console.log('Hello Promise1!');
r1();
})
.then(() => {
console.log('Hello Promise2!');
new Promise((r1, r2) => {
console.log('Hello Promise3!');
r1();
})
.then(() => {
console.log('Hello Primise4!');
})
})
문제는 then 안에 new Promise를 계속 생성하면, 위에서 봤었던 Callback지옥에 빠지게 될 것이다.
이러한 문제를 해결하도록 내부에서 실행되는 Promise는 return을 시켜주자. 그러면 내부에 있던 Promise가 Scope에서 탈출하기 때문에 내부에 있던 Promise의 then을 내부에서 아닌 외부에서 호출을 할 수 있게 된다.
const promise = new Promise((resolve,reject) =>{
//doing someting heavy work (network or data)
console.log("Doing Something")
setTimeout(()=>{
resolve('2초 지남');
},2000)
return promise; // 이 함수는 동기적 방식
})
//2. Consumer: then, catch, finally
promise
.then((value) => {
console.log(value);
})
.catch(error => {
console.lot(error);
})
.finally(()=>{
console.log("finally")
})
promise 퀴즈 풀어보기 : https://nukw0n-dev.tistory.com/17 이 퀴즈도 정말 유용할듯하다.
Async와 Await을 사용하려면 우선 사용할 함수 앞에 async라는 키워드를 붙여 사용해야 하며 선언된 async 함수 안에서만 await 키워드를 사용할 수 있다.
async & await 기본 문법
먼저 함수의 앞에 async라는 예약어를 쓴다.그리고 해당 함수 내에서 비동기 처리 로직을 수행하는 메서드 앞에 await 예약어를 붙여준다. 여기서 비동기 처리 메서드는 꼭 Promise객체를 반환해야함.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
//2초동안 기다리게 하고 사과를 리턴하는 메서드
async function getApple() {
await delay(2000);
return '🍎';
}
//1초동안 기다라게 하고 사과를 리턴하는 메서드
async function getBanana() {
await delay(1000);
return '🍌';
}
getApple().then(console.log);
getBanana().then(console.log);
const TestApiCall = () {
axios.get('https://test.com/api/v1')
.then((response) => {
const data = response.data;
const userId = data.userId;
axios.get('https://test2.com/api/v2/' + userId)
.then((response) => {
console.log("Response >>", response.data)
})
.catch(() => {
})
})
.catch((error) => {
console.log("Error >>", err);
})
}
다음 코드가 이렇게 수정될 수 있다.
const TestApiCall = async () {
try {
const response = await axios.get('https://test.com/api/v1')
const userId = response.data.userId;
const response2 = await axios.get('https://test2.com/api/v2/' + userId);
console.log("response >>", response2.data)
} catch(err) {
console.log("Error >>", err);
}
}
굿...