쉽게 동기는 직렬구조, 비동기는 병렬구조로 보면 된다.
비동기란 코드의 실행을 기다려주지 않고 다음 코드를 실행하는 구조이다.
대표적으로 setTimeout 함수가 있다.
setTimeout(()=>console.log(1),1000);
console.log(2);
이렇게 2가 먼저 출력됨을 알 수 있다.
이런 비동기 방식에서 출력 순서를 보장하기 위해 콜백함수를 사용하게 되는데 이런 콜백 함수가 여러개 중첩되다 보면 복잡도가 높아지는 콜백 헬이 발생한다.
ES6에서는 또 다른 비동기처리 방식으로 프로미스를 도입했다.
프로미스는 콜백패턴의 단점을 보완하여 명확하게 사용할 수 있는 장점이 있다.
프로미스는
pending, fulfilled, rejected
라는 3가지 상태를 가진다.
const a = fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
return response.json()
})
.then(json => {
console.log("응답!");
console.log(json)
})
.catch(err => {
console.log("에러 발생");
console.log(err);
});
console.log(a);
이렇게 프로미스의 상태를 확인 할 수 있다.
프로미스는 resolve와 reject를 사용하여 작업이 끝난 후 후속처리를 한다.
비동기처리가 성공적으로 끝날 경우 resolve를 호출하고 실패할 경우 reject를 호출하여 후속처리를 하는데 후속 처리에는 대표적으로 then과 catch가 있다.
catch는 예외가 발생하면 호출되는데
const a = fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
throw new Error("에러");
return response.json()
})
.then(json => {
console.log("응답!");
console.log(json)
})
.catch(err => {
console.log("에러 발생");
console.log(err);
});
이렇게 Error를 발생시켜보면
catch가 호출되어 에러 메세지가 호출되는 것을 알 수 있다.
async와 await은 복잡했던 Promise를 보완하여 더 간결하게 비동기 처리를 할 수 있다.
기본 문법으로는
async function(){
await ...;
}
위와 같이 표현하며 await은 항상 async함수에서만 사용할 수 있으며 async함수는 항상 프로미스를 반환한다.
또한 async/await도 try, catch로 예외 발생 처리를 할 수 있다.
이런 async/await을 사용하면
const a = fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
throw new Error("에러");
return response.json()
})
.then(json => {
console.log("응답!");
console.log(json)
})
.catch(err => {
console.log("에러 발생");
console.log(err);
});
이런 프로미스를
const func = async ()=>{
try{
const res = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const json = await res.json();
console.log("응답");
console.log(json);
}catch(err){
console.log("에러발생");
console.log(err);
}
}
func();
이렇게 간결하게 표현 할 수 있다