🗓 진행일: 2022.04.07
처음 보는 것들과 언뜻 언뜻 보았던 것들이 많아서 복습 필수

6. spread 연산자

  • 객체를 생성할 때 중복되는 값(프로퍼티)이 존재할 경우에 어떻게 하는지?
  • ... : spread 연산자, 바로 뒤에 오는 객체를 펼쳐준다는 뜻
const cookie = {
  base: "cookie",
  madeIn: "korea"
};

const chocochipCookie = {
  ...cookie,
  toping: "chocochip"
};

console.log(chocochipCookie);
  • 배열에도 사용할 수 있음
const noTopingCookies = ["촉촉한 쿠키", "안 촉촉한 쿠키"];
const topingCookies = [
  "바나나 쿠키",
  "블루베리 쿠키",
  "딸기 쿠키",
  "초코칩 쿠키"
];

const allCookies = [...noTopingCookies, "어떤 쿠키", ...topingCookies];

console.log(allCookies);
// 배열의 원소를 차례대로 붙여넣을 수 있다 신기해

7. 동기 & 비동기

우리가 처리해야 할 일이 taskA, taskB, taskC가 있다고 할 때,

  • 동기 방식의 처리
    • 싱글 스레드가 작성된 순서대로 실행하며 이전 작업이 진행 중일 때는 다음 작업을 수행하지 않음 (블로킹 방식)

    • 단점: 하나의 작업 오래 걸리면 종료 전까지 모든 게 스탑 된다 (= 흐름이 느려짐)

      // 동기
      function taskA() {
        console.log("A 작업 끝");
      }
      
      taskA();
      console.log("코드 끝");
  • 멀티 쓰레드: 작업을 각각의 스레드에게 분할
  • 근데 자바스크립트는 싱글 스레드인데요?
  • 비동기 방식
    • 여러 작업을 동시에 실행시킴

    • 작성된 코드의 결과를 기다리지 않고 바로 다음 코드를 실행 (논 블로킹 방식)

    • 각각의 task에 콜백 함수를 붙여서 작업이 끝났음을 확인한다

      // 인자로 a, b를 넘기고 a+b를 3초 뒤에 리턴하고 싶다면
      function taskA(a, b, cb) {
        // cb: 콜백 함수
        // 내장 비동기 함수 (파라미터: 콜백함수, 딜레이 타임)
        setTimeout(() => {
          const res = a + b; // 지역 상수에 저장
          cb(res);
        }, 3000);
      }
      
      function taskB(a, cb) {
        setTimeout(() => {
          const res = a * 2;
          cb(res);
        }, 1000);
      }
      
      function taskC(a, cb) {
        setTimeout(() => {
          const res = a * -1;
          cb(res);
        }, 2000);
      }
      
      taskA(3, 4, (res) => {
        console.log("A TASK RESULT : ", res);
      });
      
      taskB(7, (res) => {
        console.log("B TASK RESULT: ", res);
      });
      
      taskC(14, (res) => {
        console.log("C TASK RESULT: ", res);
      });
      
      console.log("코드 끝");
    • 결과는 코드 끝 > b > c > a

  • 자바스크립트 엔진은 Heap(메모리 할당), Call Stack(코드 실행)으로 이루어져 있음
    비동기 함수를 실행하게 되면, 비동기 함수는 Web APIs에 옮겨지게 됨
    비동기 함수에게 지정한 시간이 지나면 비동기 함수에 딸려 있던 콜백함수는 Callback Queue로 이동함
    Event Loop가 Call Stack에 어떤 실행도 남겨져 있지 않으면 Callback Queue에서 Call Stack으로 콜백 함수를 이동시킨다
taskA(4, 5, (a_res) => {
  console.log("A RESULT : ", a_res);
  taskB(a_res, (b_res) => {
    console.log("B RESULT : ", b_res);
    taskC(b_res, (c_res) => {
      console.log("C RESULT : ", c_res);
    });
  });
});

// 콜백에 콜백에 콜백을 더하는 내용이 많다

8. Promise - 콜백 지옥에서 탈출하기

  • 비동기 콜백에 콜백에 콜백을 더할 필요가 없어지게 만드는 마법의 어쩌고
  • 비동기 작업이 가질 수 있는 3가지 상태
    • Pending (대기 상태)
    • Fulfiled (성공): 이렇게 되려면 resolve (해결)
    • Rejected (실패): 이렇게 되려면 reject (거부)
  • 어떠한 값을 받아 양수인지 음수인지 구분하는 코드를 만듦
function isPositive(number, resolve, reject) {
  setTimeout(() => {
    if (typeof number === "number") {
      // 성공 -> resolve
      resolve(number >= 0 ? "양수" : "음수");
    } else {
      // 실패 -> reject
      reject("주어진 값이 숫자형 값이 아닙니다");
    }
  }, 2000);
}

isPositive(
  10,
  (res) => {
    console.log("성공적으로 수행됨 : ", res);
  },
  (err) => {
    console.log("실패하였음: ", err); //
  }
);

여기서 promise를 사용해봅시다

function isPositiveP(number) {
  const executor = (resolve, reject) => {
    // 실행자, 비동기 작업 실질적 수행
    setTimeout(() => {
      if (typeof number === "number") {
        // 성공 -> resolve
        console.log(number);
        resolve(number >= 0 ? "양수" : "음수");
      } else {
        // 실패 -> reject
        reject("주어진 값이 숫자형 값이 아닙니다");
      }
    }, 2000);
  };

  // Promise 객체를 생성하면서 executor를 넘겨줌 -> 자동으로 실행됨
  const asyncTask = new Promise(executor);
  return asyncTask;
}

const res = isPositiveP(101);

res
  .then((res) => {
    console.log("작업 성공: ", res);
  })
  .catch((err) => {
    console.log("작업 실패: ", err);
  });

promise를 쭉 이어보는 작업은 아래에...

function taskA(a, b) {
  return new Promise((resolve, reject) => {
    // executor
    setTimeout(() => {
      const res = a + b;
      resolve(res);
    }, 3000);
  });
}

function taskB(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a * 2;
      resolve(res);
    }, 1000);
  });
}

function taskC(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a * -1;
      resolve(res);
    }, 2000);
  });
}

// Promise 객체를 이용해서 then, catch로 이용하게 만들겠다~
taskA(5, 1)
  .then((a_res) => {
    console.log("A RESULT: " + a_res);
    // taskB(a_res).then((b_res) => {
    //   console.log("B RESULT: " + b_res);
    //   taskC(b_res).then((c_res) => {
    //     console.log("C RESULT: " + c_res);
    //   });
    // });
    return taskB(a_res);
  })
  .then((b_res) => {
    console.log("B RESULT: ", b_res);
    return taskC(b_res);
  })
  .then((c_res) => {
    console.log("C RESULT: ", c_res);
  });

// Promise를 이용해서 리턴하고 호출하고 리턴하고 호출하고...
// then을 계속 이어서 부르는 것: then 체이닝
// 중간에 다른 작업 하고 싶으면 return 값을 변수에 받아서 거기에 then 체인을 걸면 됨

9. async & await - 직관적인 비 동기 처리 코드 작성하기

  • async라는 키워드를 앞에 붙여서 비 동기로 만듦 (Promise로 반환하도록)
    • 비동기 작업 객체 Promise의 resolve에 리턴 값을 넣어줌
function delay(ms) {
  // ms만큼 기다렸다가 실행되게
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function helloAsync() {
  // return delay(3000).then(() => {
  //   return "hello async";
  // });
  await delay(3000); // 비동기 함수의 호출 앞에 붙이면 동기처럼 작동한다
  // async 함수 내에서만 사용 가능
  return "hello async";
}

async function main() {
  const res = await helloAsync();
  console.log(res);
}

main();

10. API 호출하기

  • 클라이언트가 서버에 데이터를 ‘요청'하여 전달 받는 과정
  • https://jsonplaceholder.typicode.com/
    • Resources: 테스트를 위해 오픈 api 제공하는 사이트
  • fetch: API 호출을 도와주는 내장 함수, Promise를 반환함 (성공 객체 자체를 반환함)
async function getData() {
  let rawResponse = await fetch("https://jsonplaceholder.typicode.com/posts");
  let jsonResponse = await rawResponse.json();
  console.log(jsonResponse);
}

getData();
profile
자존감은 일상의 성실함으로부터 온다

0개의 댓글

Powered by GraphCDN, the GraphQL CDN