모던 자바스크립트 딥다이브Chapter42~45

HYEON17·2023년 3월 7일
0

WIL

목록 보기
13/13
post-thumbnail

42장: 비동기 프로그래밍

42.1 동기 처리와 비동기 처리

자바스크립트 엔진은 싱글 스레드 방식으로 처리
현대 실행 중인 태스크가 종료할 때까지 다음에 실행될 태스크가 대기하는 방식을 동기처리라고 함

현재 실행중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행하는 방식을 비동기 처리라고 함

42.2 이벤트 루프와 태스크 큐

이벤트 루프는 자바스크립트의 동시성을 지원함

태스크 큐

  • 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역
    이벤트 루프
  • 콜스택에 현재 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기 중인 함수가 있는지 반복해서 확인

43장: Ajax

43.1 Ajax란?

자바스크립트를 사용하여 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고, 서버가 응답한 데이터를 수신하여 웹페이지를 동적으로 갱신하는 프로그래밍 방식

43.2 JSON

43.2.1 JSON 표기 방식

키와 값으로 구성된 텍스트
키는 큰따옴표로 묶어야 한다
값은 객체 리터럴과 같은 표기법을 사용
문자열은 반드시 큰따옴표로 묶어야 한다

43.2.2 JSON.stringify

객체를 JSON 포맷의 문자열로 변환
직렬화: 객체를 문자열화 하는 것

43.2.3 JSON.parse

JSON 포맷의 문자열을 객체로 변환
역직렬화: 문자열을 객체화 하는 것

43.3 XMLHttpRequest

43.3.1 XMLHttpRequest 객체 생성

브라우저에서 제공하는 Web API이므로 브라우저 환경에서만 정상적으로 실행

43.3.3 HTTP 요청 전송

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP 요청 초기화
xhr.open('GET', '/users');

// HTTP 요청 헤더 설정
// 클라이언트가 서버로 전송할 데이터의 MIME 타입 지정: json
xhr.setRequestHeader('content-type', 'application/json');

// HTTP 요청 전송
xhr.send();

44장: REST API

44.2 REST API 설계 원칙

45장: 프로미스

45.1 비동기 처리를 위한 콜백 패턴의 단점

45.1.1 콜백 헬

콜백 함수를 통해 비동기 처리 결과에 대한 후속 처리를 수행하면서 콜백 함수 호출이 중첩되어 복잡도가 높아지는 현상

45.1.2 에러 처리의 한계

에러는 호출자(caller)방향으로 전파된다

45.2 프로미스의 생성

Promise 생성자 함수는 비동기 처리를 할때 콜백함수를 인수로 전달 받는데 콜백함수는 resolve와 reject를 함수를 인수로 전달 받는다

// 프로미스 생성
const promise = new Promise((resolve, reject) => {
  // Promise 함수의 콜백 함수 내부에서 비동기 처리를 수행한다.
  if (/* 비동기 처리 성공 */) {
    resolve('result');
  } else { /* 비동기 처리 실패 */
    reject('failure reason');
  }
});

45.3 프로미스의 후속 처리 메서드

프로미스의 비동기 처리 상태가 변화하면 후속 처리 메서드에 인수로 전달한 콜백 함수가 선택적으로 호출

45.3.1 Promise.prototype.then

첫 번째 콜백 함수는 비동기 처리가 성공 했을때 호출
두 번째 콜백 함수는 비동기 처리가 실패 했을때 호출

// fulfilled
new Promise(resolve => resolve('fulfilled'))
  .then(v => console.log(v), e => console.error(e)); // fulfilled

// rejected
new Promise((_, reject) => reject(new Error('rejected')))
  .then(v => console.log(v), e => console.error(e)); // Error: rejected

45.3.2 Promise.prototype.catch

한 개의 콜백 함수를 인수로 전달 받음
프로미스가 rejected상태인 경우만 호출
catch메서드는 then과 동일하게 동작 언제나 프로미스를 반환

// rejected
new Promise((_, reject) => reject(new Error('rejected')))
  .catch(e => console.log(e)); // Error: rejected

45.3.3 Promise.prototype.finally

프로미스의 성공 또는 실패와 상관없이 무조건 한 번 호출
then/catch메서드와 마찬가지로 언제나 프로미스를 반환

new Promise(() => {})
  .finally(() => console.log('finally')); // finally

45.4 프로미스의 에러 처리

에러처리는 then메서드에서 보단 catch메서드에서 하는것을 권장
then메서드를 호출한 이후에 호출하면 비동기 처리에서 발생한 에러뿐만 아니라 then메서드 내부에서 발생한 에러까지 모두 캐치 가능

promiseGet('https://jsonplaceholder.typicode.com/todos/1')
  .then(res => console.xxx(res))
  .catch(err => console.error(err)); // TypeError: console.xxx is not a function

45.5 프로미스 체이닝

const url = 'https://jsonplaceholder.typicode.com';

// id가 1인 post의 userId를 취득
promiseGet(`${url}/posts/1`)
  // 취득한 post의 userId로 user 정보를 취득
  .then(({ userId }) => promiseGet(`${url}/users/${userId}`))
  .then(userInfo => console.log(userInfo))
  .catch(err => console.error(err));

then->then->catch 순서로 후속 처리 메서드를 호출

45.6 프로미스의 정적 메서드

45.6.1 Promise.resolve / Promise.reject

이미 존재하는 값을 래핑하여 프로미스를 생성하기 위해 사용
Promise.resolve는 인수로 전달 받은 값을 resolve하는 프로미스를 생성

// 배열을 resolve하는 프로미스를 생성
const resolvedPromise = Promise.resolve([1, 2, 3]);
resolvedPromise.then(console.log); // [1, 2, 3]

Promise.reject 메서드는 인수로 전달받은 값을 reject하는 프로미스를 생성

// 에러 객체를 reject하는 프로미스를 생성
const rejectedPromise = Promise.reject(new Error('Error!'));
rejectedPromise.catch(console.log); // Error: Error!

45.6.2 Promise.all

여러개의 비동기 처리를 모두 병렬 처리 할 때 사용

const requestData1 = () => new Promise(resolve => setTimeout(() => resolve(1), 3000));
const requestData2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000));
const requestData3 = () => new Promise(resolve => setTimeout(() => resolve(3), 1000));

Promise.all([requestData1(), requestData2(), requestData3()])
  .then(console.log) // [ 1, 2, 3 ] ⇒ 약 3초 소요
  .catch(console.error);

45.6.3 Promise.race

모든 프로미스가 fulfilled 상태가 되는것을 기다리는 것이 아니라 가장 먼저 fulfilled상태가 된 프로미스의 처리 결과를 resolve하는 새로운 프로미스를 반환

Promise.race([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
])
  .then(console.log) // 3
  .catch(console.log);

전달된 프로미스가 하나라도 rejected상태가 되면 에러를 reject하는 새로운 프로미스를 즉시 반환

Promise.race([
  new Promise((_, reject) => setTimeout(() => reject(new Error('Error 1')), 3000)),
  new Promise((_, reject) => setTimeout(() => reject(new Error('Error 2')), 2000)),
  new Promise((_, reject) => setTimeout(() => reject(new Error('Error 3')), 1000))
])
  .then(console.log)
  .catch(console.log); // Error: Error 3

45.6.4 Promise.allSettled

프로미스 요소로 갖는 배열 등의 이터러블을 인수로 전달 받는다. 전달받은 프로미스가 모두 settled 상태가 되면 처리 결과를 배열로 반환

45.7 마이크로태스크 큐

마이크로태스크 큐는 태스크큐보다 우선순위가 높다

setTimeout(() => console.log(1), 0);

Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));

2->3->1 순으로 출력
프로미스의 후속처리 메서드의 콜백함수는 마이크로태스크큐에 저장되기 때문

45.8 fetch

fetch함수는 HTTP응답을 나타내는 Response 객체를 래핑한 Promise객체를 반환
fetch 함수가 반환하는 프로미스는 기본적으로 HTTP에러가 발생해도 에러를 reject하지 않고 불리언 타입의 ok상태를 false로 설정한 Response객체를 reject한다.
네트워크 장애나 CORS에러에 의해 요청이 완료되지 못한 경우에만 프로미스를 reject한다

profile
프론트엔드 개발자

0개의 댓글