완로그
article thumbnail

⏳ 2023. 5. 22. - 2023. 5. 28.

 

동기(Synchronous)와 비동기(Asynchronous)

동기 : 코드가 순차적으로 실행된다.

비동기 : 코드가 순차적으로 실행되지 않는다.

데이터를 서버에 요청하고 응답을 받아오기까지는 어느 정도의 시간이 필요하다.

그러나 js는 따로 기다리라는 명령이 없다면, 일단 다음 코드로 넘어간다.

응답을 받고, 다음 코드로 넘어가려면 어떻게 코드를 작성해야 하는지 알아보자.


콜백과 콜백 지옥

const a = (callback) => {
  setTimeout(() => {
    console.log(1);
    callback();
  }, 1000);
};
const b = (callback) => {
  setTimeout(() => {
    console.log(2);
    callback();
  }, 1000);
};
const c = (callback) => {
  setTimeout(() => {
    console.log(3);
    callback();
  }, 1000);
};
const d = () => console.log(4);

a(() => {
  b(() => {
    c(() => {
      d();
    });
  });
});

콜백 패턴으로 비동기를 해소할 수 있으나..

코드가 길어지면 코드를 작성하기도, 읽기도 어려워진다. 🤮


Promise

const a = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(1);
      resolve();
    }, 1000);
  });
};
const b = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(2);
      resolve();
    }, 1000);
  });
};
const c = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(3);
      resolve();
    }, 1000);
  });
};
const d = () => console.log(4);

a().then(b).then(c).then(d);

오.. 한결 깔끔해졌다..

async / await

const a = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(1);
      resolve();
    }, 1000);
  });
};
const b = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(2);
      resolve();
    }, 1000);
  });
};
const c = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(3);
      resolve();
    }, 1000);
  });
};
const d = () => console.log(4);

const wrap = async () => {
  await a();
  await b();
  await c();
  d();
};

wrap();

await은 promise 인스턴스를 반환할 때만 사용할 수 있고

반드시 async 키워드와 같이 사용해야 한다.

Resolve와 Reject

콜백으로 작성한 비동기 패턴

const delayAdd = (index, cb, errorCb) => {
  setTimeout(() => {
    if (index > 10) {
      errorCb(`${index}는 10보다 클 수 없습니다.`);
      return;
    }
    console.log(index);
    cb(index + 1);
  }, 1000);
};

delayAdd(
  4,
  (res) => console.log(res),
  (e) => console.error(e)
);

promise로 바꿔 적은 비동기 패턴

const delayAdd = (index) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (index > 10) {
        reject(`${index}는 10보다 클 수 없습니다.`);
        return;
      }
      console.log(index);
      resolve(index + 1);
    }, 1000);
  });
};

// then
delayAdd(4)
  .then((res) => console.log(res))
  .catch((error) => console.error(error));

// async, await
const wrap = async () => {
  try {
    const res = await delayAdd(4);
    console.log(res);
  } catch (error) {
    console.error(error);
  }
};
wrap();

resolve는 정상적으로 실행되는 경우에, reject는 에러가 발생한 경우에 처리할 콜백 함수이다.


반복문에서 비동기 처리

forEach는 비동기 작업을 동기적으로 바꿀 수 없다.

for of를 사용하자!


fetch()

내가 정리하는 것보다.. 이 분의 글이 너무 깔끔하다..

profile

완로그

@완석이

프론트엔드 개발자를 꿈꾸는 완석이의 일기장입니다.