1. 비동기란?

자바스크립트의 비동기란 특정 작업을 수행할 때 그 작업의 결과를 기다리지 않고 다음 작업을 수행하는 것을 말한다.

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가 출력이 되는것이다.

이렇게 특정 로직이 작업을 모두 수행할 때까지 기다려주지 않고 다음 코드를 실행시키는 것이 비동기 처리이다.

2. 콜백 함수로 비동기 제어하기

그렇다면 서버에서 응답 받은 데이터를 출력하기 위해서는 어떻게 해야될 것인가?
이런 비동기 처리를 제어하기 위해 사용하는 방법 중 하나인 콜백 함수가 있다.

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로 넘겨주면
콜백 함수가 데이터를 출력하게 된다.

비동기 처리가 끝날 시점에 함수를 호출하여 제어를 할 수 있는 방법이다.

3. 콜백 지옥?

콜백 지옥은 비동기를 제어하기 위해 콜백 함수안에 다시 콜백을 넣고 그 콜백 안에 콜백을 다시 넣는 구조인데
그렇게 되면 가독성이 떨어질 뿐더러 로직을 변경하기도 굉장히 어려워진다.

그 콜백 지옥을 해결하기 위한 방법은 async와 promise가 있다.

4. Promise란?

프로미스는 3가지 상태로 이루어져 있다.

  1. Pending(대기): 처리가 아직 완료되지 않은 상태
  2. Rejected(실패): 처리가 실피해거나 오류가 발생한 상태
  3. 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의 콜백 함수 Parameterresolve, 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로 접근할 수 있으며 Parameterreject를 실행할 때의 Arguments가 넘어간다.

이렇게 promise를 사용하면 thencatch로 비동기 처리를 제어할 수 있다.

5. async & await

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(); // "실패" 출력

trycatch로 에러에 대한 예외처리를 해줄 수 있다.