JS 기초정리(5)

신태일·2024년 10월 15일

JavaScript Event Loop


console.log("1"); // 동기

setTimeout(() => {
  // 비동기
  console.log("2");
}, 3000);

console.log("3"); // 동기

setTimeout()

전역 setTimeout() 메소드는 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머를 설정한다. (두번째 매개변수로 들어간 밀리초 단위가 지난 후 첫 번째 매개변수인 콜백 함수가 호출)

비동기 코드를 작성하기 위해서 자바스크립트 이외의 도움을 받는다.

→ 위에 setTimeout도 보면 사실 자바스크립트의 일부분이 아니라 window 객체의 일부분이다. 브라우저에서 사용을 한다면 브라우저 api를 사용하는 것이며(window object), Node에서 사용한다면 Node api를 사용하는 것이다.(global object).

결국,

자바스크립트는 비동기처럼 사용할 수 있지만, 결국은 다른 것의 도움을 받아서 비동기처럼 사용할 수 있는것이다.

내부에서 어떻게 진행되는가?

console.log("1");

setTimeout(() => {
  console.log("2");
}, 3000);

console.log("3");

자바스크립트 엔진

  • 메모리 힙 - 메모리 할당이 발생하는 곳. (변수를 정의하면 저장이 되는 창고)
  • 호출 스택 - 코드가 실행될 때 스택들이 이곳에 쌓이게 된다.

Callbacks, Promise 그리고 Async, Await


자바스크립트는 싱글스레드이다.

그래서 하나의 일을 할 때 하나밖에 못하는데 만약 그 하나의 일이 오래 걸리는 일이 있다면 프로세스가 지연되게 된다. 이러한 문제점을 해결하기 위해서 비동기로 어떠한 일을 수행하게 된다.

만약 비동기 요청이 여러 개 있을 때 하나의 요청이 다른 요청의 결과에 의존한다면 ?

-> Callback 함수로 비동기 작업 해결

콜백함수는 특정 함수에 매개변수로 전달된 함수를 의미한다. 그리고 그 콜백 함수는 함수를 전달받은 함수 안에서 호출된다.

function firstFunction(parameters, callback) {
  // do something
  const response1 = request(`http://abc.com?id=${parameters.id}`);
  callback(response1);
}

function secondFunction(response1, callback) {
  const response2 = request("http://bcd.com", response1);
  callback();
}

firstFunction(para, function (response1) {
  secondFunction(response1, function () {
    thirdFunction(para, function () {
      // ...
    });
  });
});

→ 콜백 사용의 단점

  1. 위에서 볼 수 있듯이 소스 코드를 보는데 가독성이 떨어진다.
  2. 에러 처리를 한다면 모든 콜백에서 각각 에러 핸들링을 해주어야 한다.

Promise

1. Promise 객체는 new 키워드와 생성자를 사용해 만든다.

생성자는 매개변수로 “실행 함수”를 받는다. 이 함수는 매개 변수로 두 가지 함수를 받아야 하는데, 첫 번째 함수(resolve)는 비동기 작업을 성공적으로 완료해 결과를 값으로 반환할 때 호출해야 하고, 두 번째 함수(reject)는 작업이 실패하여 오류의 원인을 반환할 때 호출하면 된다. 두 번째 함수는 주로 오류 객체를 받는다.

let myFirstPromise = new Promise((resolve, reject) => {
  // 밑에서 수행한 비동기 작업이 성공한 경우 resolve(...)를 호출하고, 실패한 경우 reject(...)를 호
  // 출한다.
  // 해당 예제로는 setTimeout()을 사용해 비동기 코드를 흉내낸다.
  // 실제로는 여기서 XHR이나 HTML5 API를 사용한다.
  setTimeout(function () {
    resolve("성공!"); // 문제 없음!
  }, 250);
});

myFirstPromise.then((successMessage) => {
  // successMessage는 위에서 resolve(...) 호출에 제공한 값
  // 문자열이어야 하는 법은 없지만, 위에서 문자열을 줬으니 아마 문자열
  console.log("와! " + successMessage);
});

2. Promise는 다음 중 하나의 상태를 가진다.

  1. 대기(pending): 비동기 처리 로직이 아직 완료되지 않은 상태.
  2. 이행(fullfilled): 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태.
  3. 거부(rejected): 비동기 처리가 실패하거나 오류가 발생한 상태.


Async Await

  • 비동기 코드를 마치 동기 코드처럼 보이게 한다.
  • Promise에 then 메서드를 체인 형식으로 호출하는 것보다 가독성이 좋다.
  • await은 async 내부 함수에서만 사용할 수 있다.
  • 동기식 코드에서 쓰는 try … catch 구문을 async/await 구조에서 사용할 수 있다.
async function makeRequests() {
  try {
    const response1 = await fetch(
      "https://jsonplaceholder.typicode.com/todos/1"
    );
    const jsonResponse1 = await response1.json();
    console.log("jsonResponse1", jsonResponse1);

    const response2 = await fetch(
      "https://jsonplaceholder.typicode.com/todos/2"
    );
    const jsonResponse2 = await response2.json();
    console.log("jsonResponse2", jsonResponse2);
  } catch (error) {
    console.log(error);
  } finally {
    console.log("---모든 작업 끝---");
  }
}
profile
노원거인

0개의 댓글