자바스크립트의 비동기란 특정 작업을 수행할 때 그 작업의 결과를 기다리지 않고 다음 작업을 수행하는 것을 말한다.
function json(){
let result;
fetch("https://koreanjson.com/posts/1")
.then(res => res.json())
.then(data => {
result = data;
});
console.log(result); // undefined
}
"https://koreanjson.com/posts/1"
주소로 GET
요청을 보내면 response
로 서버에서 받아온 데이터가 담긴다.
받아온 데이터를 result
변수에 저장한 후 출력을 하게 되면 undefined
가 출력이 된다.
그 이유는 외부로 요청을 보내는 작업을 비동기로 작업했기 때문에 보낸 요청의 결과를 기다려주지 않고
바로 다음 작업인 console.log(result)
를 해버리기 때문에 undefined
가 출력이 되는것이다.
이렇게 특정 로직이 작업을 모두 수행할 때까지 기다려주지 않고 다음 코드를 실행시키는 것이 비동기 처리이다.
그렇다면 서버에서 응답 받은 데이터를 출력하기 위해서는 어떻게 해야될 것인가?
이런 비동기 처리를 제어하기 위해 사용하는 방법 중 하나인 콜백 함수가 있다.
function json(cbFunc){
fetch("https://koreanjson.com/posts/1")
.then(res => res.json())
.then(data => {
cbFunc(data);
});
}
function dataLog(data){
console.log(data);
}
json(dataLog);
위 코드는 GET
요청을 보내는것 까지는 같지만 다른 점은 함수를 Parameter
로 받는다는 점이다.
실행될 함수를 Parameter
로 받고 그 콜백 함수를 서버에서 받아온 데이터를 다시 Parameter
로 넘겨주면
콜백 함수가 데이터를 출력하게 된다.
비동기 처리가 끝날 시점에 함수를 호출하여 제어를 할 수 있는 방법이다.
콜백 지옥은 비동기를 제어하기 위해 콜백 함수안에 다시 콜백을 넣고 그 콜백 안에 콜백을 다시 넣는 구조인데
그렇게 되면 가독성이 떨어질 뿐더러 로직을 변경하기도 굉장히 어려워진다.
그 콜백 지옥을 해결하기 위한 방법은 async와 promise가 있다.
프로미스는 3가지 상태로 이루어져 있다.
1. Pending(대기): 처리가 아직 완료되지 않은 상태
1. Rejected(실패): 처리가 실피해거나 오류가 발생한 상태
1. Fulfilled(이행): 처리가 완료되어 결과 값을 반환한 상태
function json(){
return new Promise((resolve, reject) => {
fetch("https://koreanjson.com/posts/1")
.then(res => res.json())
.then(data => resolve(data));
});
}
json()
.then(data => {
console.log(data);
});
.catch(err => {
console.log(err);
});
위의 코드처럼 하게되면 콜백 함수를 넘기지 않아도 .then
으로 결과를 넘길수 있다.
new Promise((resolve, reject) =>)
우선 new Promise의 콜백 함수 Parameter
로 resolve
, reject
를 사용할 수 있다.
resolve
를 사용하게 되면
function promiseTest(){
return new Promise((resolve, reject) => {
resolve("이행");
})
}
promiseTest()
.then(data => console.log(data)) // "이행" 출력
Fulfilled(이행)
상태가 됩니다.
이행
상태가 되면 .then
으로 접근할 수 있으며 인자로 resolve
를 실행할 때의 Arguments
가 넘어간다.
reject
를 사용하게 되면
function promiseTest(){
return new Promise((resolve, reject) => {
reject("실패");
})
}
promiseTest()
.then(data => console.log(data))
.catch(err => console.log(err));
Rejected(실패)
상태가 됩니다.
실패
상퇴가 되면 .catch
로 접근할 수 있으며 Parameter
로 reject
를 실행할 때의 Arguments
가 넘어간다.
이렇게 promise
를 사용하면 then
과 catch
로 비동기 처리를 제어할 수 있다.
async & await은 비동기 처리 방법 중 가장 최근에 나온 방법이다.
function promiseTest(){
return new Promise((resolve, reject) => {
fetch("https://koreanjson.com/posts/1")
.then(res => res.json())
.then(data => resolve(data));
})
}
async function test(){
let result = await promiseTest();
console.log(result);
}
test();
await
을 사용하게 되면 마치 일반적인 동기적 코드로 동작하는 것처럼 만들어준다.
주의해야될 점은 await
을 사용할 때에는 반환되는 객체가 promise
여야 사용이 가능하고
함수에 async
를 명시해줘야 한다.
async
는 쉽게 말하자면 이 함수에서 await
을 사용하겠다고 말해주는 것이다.
promise
에서 resolve
된 결과 말고도 reject
된 결과도 async & await
을 이용하여 예외처리를 해줄 수 있다.
function promise(){
return new Promise((resolve, reject)=>{
reject("실패");
})
}
async function test(){
try{
let result = await promise();
console.log(result);
}catch(err){
console.log(err);
}
}
test(); // "실패" 출력
try
와 catch
로 에러에 대한 예외처리를 해줄 수 있다.