16. 비동기

연우·2023년 1월 22일
0

드림코딩

목록 보기
13/15
post-thumbnail
  • 자바스크립트는 기본적으로 동기적으로 진행

메모리 힙(Memory Heap)

  • 객체는 힙, 대부분 구조화되지 않은 메모리 영역에 할당된다. 변수와 객체에 대한 모든 메모리 할당은 여기서 발생한다.

호출 스택(Call Stack)

  • 코드가 실행될 때 호출 스택이 쌓인다.
function a() {
  return 1;
}

function b() {
  return a() + 1;
}

function c() {
  return b() + 1;
}
const result = c(); // 3
console.log(result);

비동기 콜백

Web API

  • 동기적으로 실행가능

  • DOM API, setTimeout, setInterval, fetch, event listener

  • 비동기 콜백 처리과정

    • 콜백 함수를 이벤트 큐(콜백 큐)에 밀어 넣고
    • 그럼 이벤트 큐는 대기하다가 스택이 텅 비는 시점에 이벤트 루프를 돌린다(스택에 넣음).
    • 이벤트 루프의 기본 역할은 큐와 스택, 두 부분을 지켜보다가 스택이 비는 시점에 콜백을 실행시켜 주는 것.
    • 각 메시지와 콜백은 다른 메시지가 처리되기 전에 완전히 처리된다.

function execute() {
  console.log('1');
  setTimeout(() => { //2초뒤에 실행해줘
    console.log('2');
  }, 2000);
  console.log('3');
}
execute();

프로미스 Promise

  • new Promise()
  • Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
  • Promise는 다음 중 하나의 상태를 가집니다.
    • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
    • 이행(fulfilled): 연산이 성공적으로 완료됨.
    • 거부(rejected): 연산이 실패함.
  • then, catch, finally
function runInDelay(seconds) {
  return new Promise((resolve, reject) => { //성공할 때 resolve, 실패할때 reject 
    if (!seconds || seconds < 0) {
      reject(new Error('seconds가 0보다 작음'));
    }
    setTimeout(resolve, seconds * 1000);
  });
}

runInDelay(2)
  .then(() => console.log('타이머 완료!'))
  .catch(console.error)
  .finally(() => console.log('끝났다!'));

프로미스 함수들

Promise.reject(reason)

  • 주어진 사유로 거부하는 Promise 객체를 반환합니다.

Promise.resolve()

  • 주어진 값으로 이행하는 Promise 객체를 반환합니다. 이때 지정한 값이 then 가능한(then 메서드를 가지는) 값인 경우, Promise.resolve()가 반환하는 프로미스는 then 메서드를 "따라가서" 자신의 최종 상태를 결정합니다. 그 외의 경우, 반환된 프로미스는 주어진 값으로 이행합니다.

  • 어떤 값이 프로미스인지 아닌지 알 수 없는 경우, 보통 일일히 두 경우를 나눠서 처리하는 대신 Promise.resolve()로 값을 감싸서 항상 프로미스가 되도록 만든 후 작업하는 것이 좋습니다.

function fetchEgg(chicken) { // fetch : 데이터를 가지고 올 때
  return Promise.resolve(`${chicken} => 🥚`);
}

function fryEgg(egg) {
  return Promise.resolve(`${egg} => 🍳`);
}

function getChicken() {
  // return Promise.reject(new Error('치킨을 가지고 올 수 없음!'));
  return Promise.resolve(`🌳 => 🐓`);
}

getChicken()
  .catch(() => '🐔') // 🌳 => 🐓
  .then(fetchEgg) // 🥚
  .then(fryEgg) // 🍳
  .then(console.log); // 🌳 => 🐓 => 🥚 => 🍳

프로미스 병렬처리

function getBanana() { 
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('🍌');
    }, 1000);
  });
} // 1초뒤에 바나나를 약속

function getApple() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('🍎');
    }, 3000);
  });
} // 3초뒤에 사과를 약속

function getOrange() {
  return Promise.reject(new Error('no orange'));
} // 오렌지가 없어 바로 에러를 던짐

// 바나나과 사과를 같이 가지고 오기
getBanana() // 바나나가 성공이 되면
  .then((banana) =>
    getApple() // 사과가 성공이 되면
      .then((apple) => [banana, apple]) // 애플을 가지고 오면 바나나와 애플 배열을 리턴
  )
  .then(console.log); // ['🍌', '🍎']
// 4초 뒤 출력 

// Promise.all 병렬적으로 한번에 모든 Promise들을 실행!
Promise.all([getBanana(), getApple()]) //
  .then((fruits) => console.log('all', fruits)); // 3초 뒤에 실행

// Promise.race 주어진 Promise중에 제일 빨리 수행된것이 이김!
Promise.race([getBanana(), getApple()]) //
  .then((fruit) => console.log('race', fruit)); // 1초 🍌

// 에러가 발생하는 것을 프로미스 all 하면?
Promise.all([getBanana(), getApple(), getOrange()]) //
  .then((fruits) => console.log('all-error', fruits))
  .catch(console.log); // 실행이 안됨

// 에러가 발생한것 성공한것 정보를 받아오고 싶다면?
Promise.allSettled([getBanana(), getApple(), getOrange()]) //
  .then((fruits) => console.log('all-settle', fruits))
  .catch(console.log);

비동기 Async

  • async function name()
  • 동기적인 코드처럼 보이지만 비동기적인 코드
  • await 키워드를 사용해서 Promise 해결을 기다린 후 값을 반환함
function getBanana() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('🍌');
    }, 1000);
  });
}

function getApple() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('🍎');
    }, 3000);
  });
}

function getOrange() {
  return Promise.reject(new Error('no orange'));
}

// 바나나과 사과를 같이 가지고 오기
async function fetchFruits() {
  const banana = await getBanana(); // 바나나를 받아 올 때까지 기다렸다가 할당하고나서
  const apple = await getApple(); // 사과를 받아 올 때까지 기다렸다가 할당하고나서
  return [banana, apple]; // 배열에 전달
}

fetchFruits() //
  .then((fruits) => console.log(fruits));

JSON

  • JSON: JavaScript Object Notation
  • 서버와 클라이언트(브라우저, 모바일) 간의 HTTP 통신을 위한 오브젝트 형태의 텍스트 포맷
  • stringify(object): JSON
  • parse(JSON): object
const ellie = {
  name: 'ellie',
  age: 20,
  eat: () => {
    console.log('eat');
  },
};

// 직렬화 Serializing: 객체를 문자열로 변환
const json = JSON.stringify(ellie);
console.log(ellie); //{ name: 'ellie', age: 20, eat: [Function: eat]}
console.log(json); // { "name": "ellie", "age": "20"}
// 데이터에 대해서는 문자열로 변환 가능하지만 함수 자체는 데이터가 아니라 포함되지 않음

// 역직렬화 Deserializing: 문자열 데이터를 자바스크립트 객체로 변환
const obj = JSON.parse(json);
console.log(obj);  // { name: 'ellie', age: 20}

REF
MDN

0개의 댓글