부트캠프/TIL

Day 26 - fs 모듈, fetch 데이터 불러오기

하이고니 2023. 1. 19. 19:06

파일 경로를 통해 데이터를 불러오기

 

가져와야 하는 데이터

// user1.json

{
  "name": "김코딩",
  "age": 26,
  "sex": "Male",
  "company": {
    "name": "코드스테이츠"
  }
}

// user2.json

{
  "name": "박해커",
  "age": 40,
  "sex": "Female",
  "company": {
    "name": "Anonymous"
  }
}

 

 

1. Callback

const fs = require("fs");

const getDataFromFile = function (filePath, callback) {
  fs.readFile(filePath, "utf8", (err, data) => {  // 콜백 함수는 err, data 두 개의 인자를 받는다.
    if(data) {
      callback(null, data);   // => null: 없음. 비어 있음.
    } else callback(err, null);   
  })
};

 

 

2. Promise Constructor

const { rejects } = require("assert");
const fs = require("fs");

const getDataFromFilePromise = filePath => {
  return new Promise((resolve, reject) => {
    fs.readFile(filePath, 'utf8', (err, data) => {
      if(data) {
        resolve(data);
      } else {
        reject(err);
      }
    })
  })
};

 

 

3. Basic Chaining

const { rejects } = require('assert');
const { resolve } = require('path');
const path = require('path');
const { getDataFromFilePromise } = require('./02_promiseConstructor');

const user1Path = path.join(__dirname, 'files/user1.json');
const user2Path = path.join(__dirname, 'files/user2.json');

// HINT: getDataFromFilePromise(user1Path) 및 
// getDataFromFilePromise(user2Path)를 이용해 작성합니다

const readAllUsersChaining = () => {

  // TODO: 여러개의 Promise를 then으로 연결하여 작성합니다
  // 나랑 페어분이 짠 코드

  // let result = [];

  // const getUser1 = () => getDataFromFilePromise(user1Path).then(
  //   data => JSON.parse(data), err => err
  //   )
  // const getUser2 = () => getDataFromFilePromise(user2Path).then(
  //   data => JSON.parse(data), err => err
  // )

  // return getUser1()
  // .then(data => {
  //   result.push(data);  
  //   return getUser2();
  // })
  // .then(data => {
  //   result.push(data);
  //   return result;
  // })

  // 이런 방식도 가능하다. 깔끔하다. 눈에 익혀두자. user1 들고 user2 받으러 가는 느낌.

  return getDataFromFilePromise(user1Path).then((user1) => {  // user1을 받아옴
    return getDataFromFilePromise(user2Path).then((user2) => {  // user2를 받아옴
      const user1Data = JSON.parse(user1);
      const user2Data = JSON.parse(user2);
      return [user1Data, user2Data];
    })
  })
}

fs 모듈로 데이터를 읽어올 경우, 그 데이터는 문자열 형태다.

JSON.parse() 를 통해서 JavaScript에서 사용할 수 있는 데이터로 변환해줘야 한다.

 

 

4. Promise.all

const { resolve } = require('path');
const path = require('path');
const { resourceLimits } = require('worker_threads');
const { getDataFromFilePromise } = require('./02_promiseConstructor');

const user1Path = path.join(__dirname, 'files/user1.json');
const user2Path = path.join(__dirname, 'files/user2.json');

const readAllUsers = () => {
  
  // 나랑 페어분이 짠 코드

  // TODO: Promise.all을 이용해 작성합니다
  // const getUser1 = () => getDataFromFilePromise(user1Path).then(
  //   data => JSON.parse(data), err => err
  //   )

  // const getUser2 = () => getDataFromFilePromise(user2Path).then(
  //   data => JSON.parse(data), err => err
  //   )

  // return Promise.all([getUser1(), getUser2()])  // Promise.all 은 배열을 인자로 받는다.
  // .then((data) => {
  //   return data;
  // })
  // // ['1초', '2초', '3초']
  // .catch((err) => console.log(err));

  // 눈에 익혀두자.
  
  return Promise.all([
    getDataFromFilePromise(user1Path), 
    getDataFromFilePromise(user2Path)
  ])
  .then(([user1, user2]) => {   // 구조 분해 할당 => [user1.json, user2.json]
      const user1Data = JSON.parse(user1);
      const user2Data = JSON.parse(user2);
      return [user1Data, user2Data];
  })
}

두 개의 Promise 객체에서 데이터를 동시에 가져와야 한다. Promise.all 은 배열을 인자로 받아서 데이터를 리턴한다.

.then의 인자로 (두 개의 데이터가 포함된) 배열을 넣어준다.

 

**Promise.all 이 리턴한 값이 배열이라서 .then의 인자로 배열을 넣어줘야 한다.

 

 

5. Async/Await

const { resolve } = require('path');
const path = require('path');
const { getDataFromFilePromise } = require('./02_promiseConstructor');

const user1Path = path.join(__dirname, 'files/user1.json');
const user2Path = path.join(__dirname, 'files/user2.json');

const readAllUsersAsyncAwait = async () => {

  // TODO: async/await 키워드를 이용해 작성합니다
  // 나랑 페어분이 짠 코드

  // let result = [];

  // const getUser1 = () => getDataFromFilePromise(user1Path).then(data => {
  //   result.push(JSON.parse(data));
  //   return result;
  // })

  // const getUser2 = () => getDataFromFilePromise(user2Path).then(data => {
  //   result.push(JSON.parse(data));
  //   return result;
  // })

  // await getUser1();
  // return await getUser2();

  // 눈에 익혀두자....... 개깔끔하네
  
  const user1 = JSON.parse(await getDataFromFilePromise(user1Path));   
  // 함수 리턴값은 user1의 json 데이터. await는 promise의 result를 꺼낸다.
  const user2 = JSON.parse(await getDataFromFilePromise(user2Path));   
  // 함수 리턴값은 user2의 json 데이터. await는 promise의 result를 꺼낸다.
  return [user1, user2];
  
}

fetch로 데이터 불러오기

 

가져와야 하는 데이터

// newsURL 

{ "data": [ 
	{
    	"row_id": 2, 
        "title": "2021년 경제 성장률 전망 밝아",
        "source": "A신문",
        "timestamp": "2020/12/30"
     },
     {
     	"row_id": 3,
        "title": "코로나19 증가추세 대폭 하락해",
        "source": "BBC",
        "timestamp": "2020/12/29"
     },
     {
     	"row_id": 4,
        "title": "코드스테이츠 취업연계 파트너사 xxx건 돌파",
        "source": "스타트업 뉴스",
        "timestamp": "2020/12/31"
     }
	]
}

// weatherURL

{
    "status": "sunny",
    "temperature": "28",
    "fineDust": "good"
}

 

주의 사항!!

weatherURL의 데이터는 그냥 불러오면 되지만, newsURL의 데이터는 "data"라는 key의 value 값만 뽑아서 써야한다.

 

 

1. Basic Chaining

const newsURL = 'http://localhost:4999/data/latestNews';
const weatherURL = 'http://localhost:4999/data/weather';

function getNewsAndWeather() {


  // 나랑 페어분이 짠 코드

  // let result = {};

  // const getNews = fetch(newsURL)    // 프로미스 객체?
  // .then((response) => response.json())
  // .then((json) => json)
  // .catch((error) => error);

  // const getWeather = fetch(weatherURL)
  // .then((response) => response.json())
  // .then((json) => json)
  // .catch((error) => error);

  // return getNews
  // .then(data => {
  //   result['news'] = data['data'];
  //   return getWeather;
  // })
  // .then(data => {
  //   result['weather'] = data;
  //   console.log(result);
  //   return result;
  // })

  // .json => Response 안에서 원하는 데이터를 꺼내와서 
  	// JavaScript가 원하는 형식으로 바꿔서 result에 갖고 있는다.
  // 1. await 로 바로 data 꺼낼 수 있음.
  // 2. .then 붙여서 꺼낼 수 있음.

  return fetch(newsURL)     
  // Promise 객체 리턴. state 와 result 라는 내부 속성이 있음. result 안에 response가 있다.
  .then((res) => res.json())  
  // response 안에서 data 꺼낸 다음, news에 넣어~ => news에는 result 안에 들어있는 data가 들어간다.
  .then(({ data: news }) => { 
  // 와 이거 졸래 어렵다 ㅋㅋㅋㅋㅋㅋㅋㅋ data: value => value만 갖고 오고 싶다~~
    return fetch(weatherURL)
    .then((res) => res.json())
    .then((weather) => {
      return {
        news,               // 키 이름과 value의 변수명이 같으면 축약 가능..
        weather
      };
    });
  });
}

 

 

2. Promise.all

function getNewsAndWeatherAll() {
  // TODO: Promise.all을 이용해 작성합니다

  // 나랑 페어분이 짠 코드

  // const getNews = fetch(newsURL)
  // .then((response) => response.json())
  // .then((json) => json)
  // .catch((error) => error);

  // const getWeather = fetch(weatherURL)
  // .then((response) => response.json())
  // .then((json) => json)
  // .catch((error) => error);

  // return Promise.all([getNews, getWeather])  // Promise.all 은 배열을 인자로 받는다.
  // .then((data) => {
  //   let result = {};

  //   result['news'] = data[0]['data'];
  //   result['weather'] = data[1];
    

  //   return result;  
  // })
  // .catch((err) => err);

  // 이렇게 계속 두개씩 갖고갈 수 있다.
  
  return Promise.all([fetch(newsURL), fetch(weatherURL)])
  .then(([res1, res2]) => {
    return Promise.all(([res1.json(), res2.json()]))
    .then(([{data: news}, weather]) => {
      return { news, weather };
    })
  })
}

 

 

3. Async/Await

// pending: 실행되기 전
// let a = 2; undefined 뜨는 것처럼 fecth 선언하면 Promise{<pending>}


async function getNewsAndWeatherAsync() {
  // TODO: async/await 키워드를 이용해 작성합니다

  // 나랑 페어분이 짠 코드

  // const getNews = fetch(newsURL)
  // .then((response) => response.json())
  // .then((json) => json)
  // .catch((error) => error);

  // const getWeather = fetch(weatherURL)
  // .then((response) => response.json())
  // .then((json) => json)
  // .catch((error) => error);

  // await getNews;
  // await getWeather;

  // return Promise.all([getNews, getWeather])  // async 함수는 반드시 promise를 반환해야 한다.
  
  // .then((data) => {
    
  //   let result = {};

  //   result['news'] = data[0]['data'];
  //   result['weather'] = data[1];

  //   return result;  
  // })
  // .catch((err) => err);

  const { data: news } = await fetch(newsURL).then(res => res.json());  // 구조.. 분해.. 할당......
  
  // { data: news } = { data: 내가 진짜 원하는 데이터 } 
  // => news 라는 변수에 내가 진짜 원하는 데이터를 할당
  
  const weather = await fetch(weatherURL).then(res => res.json());
  return { news, weather };
  
  // let arr = [1, 2];
  // let a = arr[0], b = arr[1]; 

  // => let [a, b] = [1, 2];
  // => a === 1, b === 2

  // {a, b} = { a: 1, b: 2 }
  // a === 1, b === 2
  // spread, 구조 분해 할당, async/await => 무조건 암기

  // JSON.parse, .json() => JSON 포맷의 데이터를 자바스크립트의 데이터로 변환한다는 공톰점은 있지만, 
  // json()은 result에 담는다는 특징.
  // 실제로는 fetch 안 쓴다. axios 쓴다.

}