혼자 적어보는 노트

프로그래머스 데브코스 TIL - Day 13 본문

스터디

프로그래머스 데브코스 TIL - Day 13

jinist 2022. 4. 6. 17:40

 학습 목차

- [DAY 13] VanillaJS를 통한 자바스크립트 기본 역량 강화 (5)

 

✅ 새롭게 학습한 부분

- fetch api

 


 

fetch API

 

- 비동기 http요청을 좀 더 쓰기 편하게 해주는 api

- XMLHTTPRequest를 대체 🙌

- Promise기반으로 동작한다 ( = then, async await 가능)

 

데이터 요청을 통해 Response 객체를 받은 후에는 json이나 text로 바꾸어서 사용한다.

 

.blob() 

const $image = document.createElement("img");
const imageUrl = "https://cors-anywhere.herokuapp.com/http://placeimg.com/640/480/any";
//cors 에러가 생겨서 https://cors-anywhere.herokuapp.com 사용

fetch(imageUrl)
  .then((res) => {
    return res.blob();
  })
  .then((data) => {
    console.log(data);
    const url = URL.createObjectURL(data);
    console.log(url);
    
    $image.src = url;
    document.querySelector("body").appendChild($image);
  });

직접 활용을 해 본 적은 없지만

해당 메소드를 사용하면 Blob객체를 받아와서 동적으로 사용할 수 있게 해준다.

 

fetch API에서 HTTP error 처리

❗❗ fetch API는 HTTP error가 발생하더라도 reject 되지 않는다!

res.status의 code나 res.ok를 확인해서 처리를 해주어야 한다.

fetch(url)
  .then((res) => {
    if (res.ok) {
      return res.json();
    }
    throw new Error("");
  })
  .then((data) => console.log(data))
  .catch((e) => console.log(e.message));

 

중첩된 request 요청

불러온 데이터를 사용해서 한번 데이터를 요청하고 받아올 수 있다.

const fetchOptionData = (productId) => {
  return request(`/products/${productId}`)
  // 1. product id를 통해 해당 product의 Data를 불러오고
    .then((product) => {
      return request(`/product-options?product.id=${product.id}`);
      // 2. 불러온 Product의 id를 사용하여 해당 product의 options를 불러온다
    })
    .then((productOptions) => {
      console.log(productOptions);
    });
};

 

 

Promise.all()의 활용

Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스를 이행하고

이행한 결과인 Promise객체들을 배열로 담아서 준다.

-> 배열안에 프로미스가 담겨있으면 동시 실행 가능

 

활용 1. 데이터를 여러개 요청하여 한번에 묶을 때 

.then((productOptions) => {
      console.log(productOptions);
      return Promise.all(
        productOptions
          .map((productOption) => productOption.id) // 불러온 Data의 id만 남긴 배열 만들기
          .map((id) => { // id를 활용하여 배열에 promise 넣기
            return request(`/product-option-stocks?productOption.id=${id}`);
          })
      );
    });

위 예시는 map을 2번 돌렸지만 한번만 돌려도 결과가 같았다.

productOptions.map((productOption) => {
  return request(`/product-option-stocks?productOption.id=${productOption.id}`);
})

 

활용2. then으로 넘기기 위한 Promise.all() 사용

    .then((productOptions) => {
      console.log(productOptions);
      return Promise.all([
        Promise.resolve(productOptions), // promise객체를 그대로 반환
        Promise.all(
          productOptions.map((productOption) => {
            return request(`/product-option-stocks?productOption.id=${productOption.id}`);
          })
        ),
      ]);
    })
    .then((data) => {
      const [productOptions, stocks] = data; // 요소2개를 가진 배열이 리턴됨
      console.log(data);
    });

then으로 넘기기 위해 Promise.all()로 감싼 형태.

promise.all()을 하여 받은 데이터를 기존 then의 데이터와 함께 다음 then으로 넘기기 위해

한번 더 Promise.all()을 사용한 것이라고 볼 수 있다.

 

 

Response Data 가공하기

then 체인을 사용하여 여러 데이터를 받아서

마지막 then에서 원하는 형태로 데이터를 가공해서 전달할 수 있다.

    .then((data) => {
      const [productOptions, stocks] = data;
      const optionData = productOptions.map((productOption, i) => {
        const stock = stocks[i][0].stock;

        return {
          optionId: productOption.id,
          optionName: productOption.optionName,
          optionPrice: productOption.optionPrice,
          stock,
        };
      });
      console.log(optionData);
    });

 

 

string.startsWith()

어떤 문자열이 특정 문자로 시작하는지 확인하여 결과를 true 혹은 false로 반환한다.

강의를 들으며 처음 접하게 된 부분이다.😲

아래와 같이 전달되는 url의 첫 글자가 /인지 체크하여 사용할 수 있다.

export const request = (url) => {
  return fetch(`${API_END_POINT}${url.startsWith("/") ? url : `/${url}`}`)
  // 생략
};

 

 


✍ 느낀 점

 

오늘 강의의 주된 내용은 fetch의 활용이었다.

지금까지 난 respanse 받은 한 개의 데이터를 then으로 연결해서 다루어 본 적은 있었지만

then을 사용하여 여러개의 request를 중첩해서 다루어 본 적은 없었다.

여러 request를 받고 데이터를 조합해서 새로운 형태의 데이터를 만든다는 것을 직접 보니 새로웠다.

비동기로 데이터들을 다루는 것이 은근히 까다롭다고 말로만 들었었는데

방식들을 살펴보니 까다롭다는 말이 이해가 되었다. 😅

강의 내에서는 초심자들의 이해를 돕기 위해 간단한 데이터를 다루셨고, 데이터를 일일히 불러 오셨지만

많은 데이터를 효율적으로 응답하고 요청하려면 클라이언트 쪽이나 서버 쪽이나

서로 고려할 점이 많을 것 같다는 생각이 들었다.

 

Comments