🌼 async-await / Promise - Callback
앞서 동기/비동기가 무엇인지 부터 알고 넘어가자
시간이 오래 걸리는 일을 동기적(Sync)로 처리하게 되면, 그 작업이 처리될 때까지 클라인언트가 서버에 들어가지 못한다.
1️⃣ 동기 / 비동기
🐶 동기
요청을 하면 시간이 얼마나 걸려도 요청한 자리에서 결과가 기다리는 방식
🐶 비동기
요청과 결과가 동시에 일어나지 않는 방식
GET 메소드를 사용해서 서버와 통신으로 데이터를 조회할때
데이터를 요청하고, 기다리지 않고 바로 다음 코드로 넘어가 버리기 때문에 원하는 데이터를 받을 수 없다.
Callback 함수를 Promise로 받는다.
⛔️ 이러한 이유
자바스크립트는(싱글 스레드) 한번에 하나의 함수만 실행할 수 있기 때문이다.
비동기 코드는 콜 스택에서 실행하는 것은 가독성이 좋지 않아 이벤트 루프를 통해 실행된다.
V8 엔진으로 인해 브라우저 내부,외부에서도 동작이 가능해진다.
V8 엔진 + 런타임 -> 이벤트 루프 작동(비동기 처리를 가능하게 해주는 일종의 시스템)
1. 싱글 스레드 : 하나의 프로세스에서 하나의 스레드 실행
2. 멀티 스레드 : CPU의 최대 활용을 위해 프로그램의 둘 이상을 동시에 실행
2️⃣ 이벤트 루프
비동기를 처리하는 방법
call stack이 다 비워지면 callback queue에 존재하는 함수를 하나씩 call stack으로 옮기는 역할을 한다.
콜 스택과 콜백 큐를 계속 주시하다가 콜 스택이 비어있으면
먼저 들어온 순서대로 콜백 큐에 있는 함수들을 콜 스택에 집어 넣는 것을 의미함
1. 콜 스택 : LIFO(후입 선출) 스택
- 콜 스택을 지속적으로 확인하여 실행해야 하는 함수가 있는지 확인한다.
2. 콜백 큐 : FIFO(선입 선출)
- JavaScript는 실행할 작업을 찾고 순서대로 실행한다.
출처 : velog
3️⃣ Callback
함수가 실행을 끝낸 뒤 실행되는 함수 즉, 나중에 호출되는 함수다.
🫥 Callback 지옥
Callback함수 호출 Callback함수 호출 ...
아래 처럼 콜백 함수를 계속 호출 할 수 있다.
const myCallback = () => {
const aa = new XMLHttpRequest()
aa.open("get", `http://numbersapi.com/random?min=1&max=200`)
aa.send()
aa.addEventListener("load", (res) => {
console.log(res)
const num = res.target.response.split("")[0]
const bb = new XMLHttpRequest()
bb.open("get", `https://koreanjson.com/posts/${num}`)
bb.send()
bb.addEventListener("load", (res) => {
console.log(res);
const userId = JSON.parse(res.target.response).id
const cc = new XMLHttpRequest()
cc.open("get", `https://koreanjson.com/posts?userId=${userId}`)
cc.send()
cc.addEventListener("load", (res) => {
console.log(res);
})
})
})
}
이러한 것을 콜백 지옥이라고 한다.
콜백 지옥은 가독성저하의 문제로 이를 해결하기 위해 Promise가 있다.
4️⃣ Promise
javascript에서 비동기 처리를 할 때 이용하는 객체
Promise를 통해 로직이 미완료,완료,실패 했는지에 따라 상태가 결정된다.
1. Promise {<pending>} 대기 ( pending ) - 미완료 상태
2. Promise {<fullified>} 이행 ( fullified ) - 완료 상태
3. Promise {<rejected>} 거부 ( rejected ) - 실패 상태
비동기 작업이 끝나면 결과를 resolve로 전달, 에러를 reject로 전달
then과 catch로 결과를 받는다. resolve로 전달받은 결과가 then, reject로 전달받은 에러 catch
new Promise((성공했을때 실행시킬 함수, 실패했을때 실행시킬 함수)=>{
try {
const response = "철수"
성공했을때 실행시킬 함수(response)
} catch (err) {
console.log(err)
실패했을때 실행시킬 함수("실패했습니다.!")
}
}).then((res) =>{
console.log(res);
}).catch((err)=>{
console.log(err);
})
콜백지옥의 가독성을 보안하기 위해 나온 개념이긴 하나 then()지옥도 가능
then()지옥의 가독성을 보안하기 위해 나온 개념 async-await
5️⃣ async-await
await 은 async 함수 안에서만 동작한다.
await 은 비동기 처리를 동기적인 것 처럼 처리할 수 있게 해준다.
async 는 promise 객체로 보내지게 된다.
const myAsyncAwait = async () => {
try {
const aa = await axios.get(`http://numbersapi.com/random?min=1&max=200`)
const num = aa.data.split("")[0]
const bb = await axios.get(`http://koreanjson.com/posts/${num}`)
const userId = bb.data.id
const cc = await axios.get(`http://koreanjson.com/posts?userId=${userId}`)
console.log(cc);
} catch (err) {
console.log(err)
}
}
async-await은 에러가 발생해도 반응이 없기 때문에 try-catch문을 활용하여 에러 핸들링을 해줘야 한다.