728x90
반응형
1) Javascript 기초
1-1) callback hell
1-2) Promise
1-3) async/await
1) Javascript 기초
학습 순서
- callback
- Promise
- async/await
socket.on('data', (chunk) => {
console.log(chunk);
})
// 비동기 코드: 언제 올지 모르는 코드
// 콜백 함수 안에서 다시 콜백 함수를 실행하는 것을 여러번 반복한 상황을 "callback hell"이라 부른다!!
// "callback hell"이 나올 수밖에 없는 이유는 비동기 코드를 처리하기 위함이다!
// 이 과정에서 "이벤트 기법"이라는 것을 활용해 처리함!
net.createServer((socket) => {
socket.on('data', (chunk) => {
const req = request(chunk);
})
})
// 1. 서버를 연다.
// 2. 데이터를 받는다.
1-1) callback hell
// callback hell
const avante = () => {
setTimeout(() => {
console.log("avante go");
}, 3000);
};
const sonata = () => {
setTimeout(() => {
console.log("sonata go");
}, 2000);
};
const genesis = () => {
setTimeout(() => {
console.log("genesis go");
}, 1000);
};
// 위의 상황의 경우, Client 입장에서 서버에게 요청을 한다면 3개의 요청을 보내고,
// 이에 대한 3개의 응답을 받는 상황이다!!
// 문제)
// 그럼 avante 요청 후 응답이 오면
// 그 후 sonata 요청 후 응답이 오게한 뒤
// 그리고나서 genesis를 요청하고 응답이 오도록 함!
const avante = () => {
setTimeout(() => {
console.log("avante go");
sonata();
}, 3000);
};
const sonata = () => {
setTimeout(() => {
console.log("sonata go");
genesis();
}, 2000);
};
const genesis = () => {
setTimeout(() => {
console.log("genesis go");
}, 1000);
};
avante();
// 바로 위의 풀이의 문제점 : 확장성 문제(예를 들어 avante 함수를 실행시키면 반드시 sonata 함수를 실행시킬 수밖에 없는 구조이기 때문이다!!)
// 위의 문제를 해결하기 위한 코드형태
const avante = (callback) => {
setTimeout(() => {
console.log("avante go");
callback();
}, 3000);
};
const sonata = (callback) => {
setTimeout(() => {
console.log("sonata go");
callback();
}, 2000);
};
const genesis = (callback) => {
setTimeout(() => {
console.log("genesis go");
callback();
}, 1000);
};
avante(() => {
sonata(() => {
genesis(() => {
console.log("end");
});
});
});
const avante = (callback) => {
setTimeout(() => {
console.log("avante go");
callback();
}, 3000);
};
const sonata = (callback) => {
setTimeout(() => {
console.log("sonata go");
callback();
}, 2000);
};
const genesis = (callback) => {
setTimeout(() => {
console.log("genesis go");
callback();
}, 1000);
};
// 문제2)
// avante 요청 후 응답받고,
// avante 요청 후 응답받고,
// genesis 요청 후 응답받고,
// sonata 요청 후 응답받고,
// avante 요청 후 응답받고,
// sonata 요청 후 응답받는 코드 구현
avante(() => {
avante(() => {
genesis(() => {
sonata(() => {
avante(() => {
sonata(() => {});
});
});
});
});
});
1-2) Promise
Promise : 비동기 코드에 대한 "callback hell"을 해결하기 위해 등장함!
Promise는 기본적으로 return 값이 객체(Object)이다!!
// Promise 객체의 기본 형태
const pr = new Promise((resolve, reject) => {});
// Promise는 return 값이 객체(Object)이며(이는 new 키워드가 붙었다는 점에서 확인가능!), 생성자 함수의 인자값으로 무조건 함수를 받는다!!
// Promise의 2가지 매개변수
// 1) resolve : 성공했으면 resolve 함수의 인자값으로 넣어주라는 의미
// 2) reject : 실패했으면 reject 함수의 인자값으로 넣어주라는 의미
const pr = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("OK");
// reject("Not OK");
}, 3000);
});
console.log(pr);
// Promise { state : <pending>, result : undefined }
// Promise { state : <fulfilled>, result : 'OK' }
// Promise { state : <rejected>, result : 'Not OK' }
// Promise 객체는 기본적으로 "상태(state)"를 가진다!
// 여기서 상태(state)는 3가지 형태로 나뉘어져 있는데 이는 "pending(비동기 코드가 완료되지 않은 상태)", "fulfilled", "rejected"이다!
// "pending"은 아직 요청 중인 것이고 함수를 호출하게 되면 resolve이면 "fulfilled", reject이면 "rejected"이다!
// Promise 객체는 "then"과 "catch", 그리고 "finally" 메서드가 있다!
// then 메서드는 resolve이면서 상태가 "fulfilled"일 때 실행시켜 줌!!
pr.then((data) => {
// then의 인자값(data)에는 Promise 객체의 result 값이 담긴다!
console.log(data);
});
// 기존의 callback 함수를 Promise 객체로 변환해 봄!
const avante = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("avante go");
}, 3000);
});
};
const sonata = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("sonata go");
}, 2000);
});
};
const genesis = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("genesis go");
}, 1000);
});
};
// Promise 체이닝
console.time("x"); // 해당 코드를 통해 아래 코드 구문 실행 시 시간이 얼마나 걸리는지 체크할 수 있음!!
avante()
.then((data) => {
console.log(data);
return sonata();
})
.then((data) => {
console.log(data);
return genesis();
})
.then((data) => {
console.log(data);
console.timeEnd("x");
});
/*
// 문제3)
// avante 요청 후 응답받고,
// avante 요청 후 응답받고,
// genesis 요청 후 응답받고,
// sonata 요청 후 응답받고,
// avante 요청 후 응답받고,
// sonata 요청 후 응답받는 코드 구현
avante()
.then((data) => {
console.log(data);
return avante();
})
.then((data) => {
console.log(data);
return genesis();
})
.then((data) => {
console.log(data);
return sonata();
})
.then((data) => {
console.log(data);
return avante();
})
.then((data) => {
console.log(data);
return sonata();
})
.then((data) => {
console.log(data);
});
*/
1-3) async/await
callback : tab index, 즉 들여쓰기가 너무 많다는 단점이 있다!
Promise : Promise 객체를 만드는 것이 어렵고, 사용할 때 조금 코드가 많다는 단점이 있다!
async/await : 위의 문제들을 해결하기 위해 등장함!
const avante = async () => {
return "avante go";
};
console.log(avante()); // Promise 객체가 반환됨! <-- 여기서는 { <pending> }이 출력됨!
// avante().then((data) => {
// console.log(data); // avante go
// });
// "async"를 달면 "await"을 쓸 수 있음!!
// await : 해당 함수 실행 후 then이 떨어질 때까지 기다렸다가 결과물(then 메서드의 인자값에 담기는 result 값)을 받아서 담아줌!!
// init 함수 : Promise 객체를 받아주는 함수(Promise 객체를 관리해주는 함수)
const init = async () => {
const result = await avante(); // await이 되는 것은 반드시 Promise 객체여야 한다!!
console.log(result);
};
init();
const avante = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("avante go");
}, 3000);
});
};
const sonata = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("sonata go");
}, 2000);
});
};
const genesis = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("genesis go");
}, 1000);
});
};
const init = async () => {
const result = await avante(); // await이 되는 것은 반드시 promise 객체여야 한다!!
console.log(result);
const result2 = await sonata();
console.log(result2);
const result3 = await genesis();
console.log(result3);
};
init();
/*
// 문제4)
// avante 요청 후 응답받고,
// avante 요청 후 응답받고,
// genesis 요청 후 응답받고,
// sonata 요청 후 응답받고,
// avante 요청 후 응답받고,
// sonata 요청 후 응답받는 코드 구현
const init = async () => {
const result1 = await avante();
console.log(result1);
const result2 = await avante();
console.log(result2);
const result3 = await genesis();
console.log(result3);
const result4 = await sonata();
console.log(result4);
const result5 = await avante();
console.log(result5);
const result6 = await sonata();
console.log(result6);
};
init();
*/
/*
// init2 함수를 실행시키면 해당 내용은 background에 들어감!!
let rst = "아무것도 없니?";
const init2 = async () => {
const result = await avante();
rst = result;
};
init2();
console.log(rst); // 아무것도 없니?
*/
(중요!!) "async"가 달려 있으면 해당 함수는 background에 들어가게 되고, 거기서 기다리다가 이후 실행된다!!
// Promise를 사용해야 하는 경우
// Promise.all([]);
const avante = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("avante go");
}, 3000);
});
};
const sonata = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("sonata go");
}, 2000);
});
};
const genesis = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("genesis go");
}, 1000);
});
};
const init = async () => {
// const result1 = await avante();
// console.log(result1);
// const result2 = await genesis();
// console.log(result2);
// const result3 = await sonata();
// console.log(result3);
// 배열 안에 Promise 객체들만 들어갔을 경우 --> [Promise{}, Promise{}, Promise{}]
/*
Promise.all([avante(), sonata(), genesis()]).then((data) => {
console.log(data);
});
*/
console.time("x");
// const result = await Promise.all([avante(), sonata(), genesis()]);
// console.log(result);
// 배열 구조분해할당 활용
const [a, b, c] = await Promise.all([avante(), sonata(), genesis()]);
console.log(a, b, c);
console.timeEnd("x");
};
init();
'Javascript > Javascript(2022 version)' 카테고리의 다른 글
Javascript 복습(2) - 클로저, 로또 Refactoring (0) | 2022.12.16 |
---|---|
Javascript 복습 - 스코프, 호이스팅, function 키워드, this binding (0) | 2022.12.15 |
Javascript 기초(7) - 함수, 콜스택, 스코프 체인, this (0) | 2022.11.26 |
Javascript 기초(6) - 상속 및 메서드 (0) | 2022.11.04 |
Javascript 기초(5) - 객체 및 메서드 (0) | 2022.11.03 |