2020.코딩일지

[JS/Node]PART2-Node.js의fs모듈(callback,promise,async) [BEB 6th] 본문

JS & React

[JS/Node]PART2-Node.js의fs모듈(callback,promise,async) [BEB 6th]

개발하는라푼젤 2022. 7. 26. 19:19
728x90

Node.js란? 비동기 이벤트 기반! 로컬환경에서 자바스크립트를 실행할 수 있는 '자바스트립트 런타임'

브러우저 환경과는 다르게 Node.js환경은 로컬컴에서 직접 실행되므로

파일을 불러오거나(파일열기) 저장하는(파일저장하기) 등의 액션이 가능하다. (비동기상황을 연출하여 연습할 수 있다)

Node.js의내장모듈목록

DNS모듈사용법

const fs = require('fs'); //파일시스템 "전체"모듈이 불러옴
const { readFile } = require("fs"); // readFile만 쏙뽑았
const dns = require('dns');//DNS모듈을 불러옴

   fs(Filse System)module

파일읽기`readFile`

파일저장`writeFile`

fs.readFile(path[, options], callback) 비동기적으로 파일내용전체를 읽음. 이 메소드는 인자 세 개를 넘길 수 있다.

더보기

•`path`에는 파일 이름을 인자로 넘길 수 있다. 네가지<string,buffer,URL,inreger>타입가능하지만 보통 문자열로ㄱㄱ

예를들어 etc/passwd파일을 불러오려면 `fs.readFile('/etc/passwd', ..., ...)` 이런식

•`options` []안에있는건 넣어도되고안넣어도되고~선택적인 인자. <Object,string>객체,문자열타입이 가능하지만

문자열로 전달할 경우 인코딩을 넘김 (utf8이 두 번째 인자)

•`callback`<Function>  콜백함수를 전달한다. 파일을 읽고 난후에 비동기적으로 실행되는 함수.

실패err인경우<Error>

성공data인경우<string 또는 Buffer>

 

PART2 - fs모듈 

Node.js에서는 파일을 읽는 비동기 함수를 제공한다. callback과 Promise로 구현해보자!

fs.readFile 공식API문서

Promise.all 자료를한번에받아감(하나라도 f면 .catch)

JSON.parse() 객체화

__dirname 현재실행중인 폴더 (Node.js에서 경로를 다룰 때, `__dirname`과 `path` module이 유용하다!

 

📒01_callBack.js

//📒01_callBack.js
const { readFile } = require("fs"); //😎fs모듈에서 readFile만 쏙뽑아옴

const getDataFromFile = function (filePath, callback) {
  readFile(filePath, "utf8", function (err, text) {
    if (err) { 				//에러일경우
      callback(err, null); //에러와 data자리에 null을 주고
    } else { 				//성공일경우
      callback(null, text); //에러null과 data를 드립니다
    }
  });
};

// getDataFromFile('README.md', (err, data) => console.log(data));

module.exports = {
  getDataFromFile
};

 

📒02_promiseConstructor.js

callback파라미터(인자)대신 😎Promise의 reject, resolve사용

//📒02_promiseConstructor.js
const { readFile } = require("fs");

const getDataFromFilePromise = filePath => {
//😎callback파라미터(인자)대신 Promise의 reject, resolve사용
  return new Promise((resolve, reject) => { 
    readFile(filePath, "utf8", function (err, text) {
      if (err) {			//에러일경우
        reject(err);		//reject처리
      } else {				//성공일경우
        resolve(text);		//resolve처리
      }
    });
  });
};

// getDataFromFilePromise('README.md').then(data => console.log(data));

module.exports = {
  getDataFromFilePromise
};

 

📒03_basicChaining.js

02_promiseConstructor에서 작성한 `getDataFromFilePromise`를 이용해 user.json 받아옴. 

합쳐서 "두 객체가 담긴 배열"을 만드는 것이 목표

.then이 어떠한 파라미터를 전달받는가?

파일읽기의 결과는 문자열이므로, `JSON.parse`사용하기.

😎비동기적인 코드로 되어 있지만, 동기적으로 작동하는 것을 확인할 수 있다.
//📒03_basicChaining.js
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 readAllUsersChaining = () => {
  return new Promise((resolve, reject) => {
    resolve(
      getDataFromFilePromise(user1Path)
        .then(JSON.parse)
        .then((obj1) => { 		//user1열어 JSON.parse(객체로변환)후 onj1에 담고
          return getDataFromFilePromise(user2Path)
            .then(JSON.parse)	//user2열어 JSON.parse후 onj2에 담아
            .then((obj2) => [obj1, obj2]); //배열로반환
        })
    );
  });
};

// readAllUsersChaining();

module.exports = {
  readAllUsersChaining,
};
//📒03_basicChaining.js - 방법2.
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 readAllUsersChaining = () => {
  return getDataFromFilePromise(user1Path)
    .then((user1) => {
      return getDataFromFilePromise(user2Path).then((user2) => {
        return "[" + user1 + "," + user2 + "]"; //코드스테이츠 레퍼런스방식
        //또는 `[${user1},${user2}]`
      });
    })
    .then((text) => JSON.parse(text));
};

// readAllUsersChaining();

module.exports = {
  readAllUsersChaining,
};

 

📒04_promiseAll.js

03.basicChaining과 같은 결과를 리턴하지만 Promise.all을 사용한다.

//📒04_promiseAll.js - 방법1
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");
//03.basicChaining과 같은 결과를 리턴하지만 Promise.all을 사용한다.
const readAllUsers = () => {
  return Promise.all([
    getDataFromFilePromise(user1Path),
    getDataFromFilePromise(user2Path),
  ])
    .then((values) => {
      return `[${values[0]}, ${values[1]}]`;
    })
    .then((text) => JSON.parse(text));
};

readAllUsers();

https: module.exports = {
  readAllUsers,
};
//📒04_promiseAll.js - 방법2 readAllUsers함수부분만
const readAllUsers = () => {
  let data1 = getDataFromFilePromise(user1Path);
  let data2 = getDataFromFilePromise(user2Path);

  return Promise.all([data1, data2]).then((value) => {
    return value.map((el) => JSON.parse(el));
  }); //😎map을사용하여 각각 JSON객체화
};
//📒04_promiseAll.js - 방법3
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");
//03.basicChaining과 같은 결과를 리턴하지만 Promise.all을 사용한다.

const readAllUsers = () => {
  return Promise.all([getUser1, getUser2]).then((values) => [
    values[0],
    values[1],
  ]);
};

const getUser1 = getDataFromFilePromise(user1Path).then((json) =>
  JSON.parse(json)
);

const getUser2 = getDataFromFilePromise(user2Path).then((json) =>
  JSON.parse(json)
);

readAllUsers().then((result) => console.log(result));

https: module.exports = {
  readAllUsers,
};

 

📒05_asyncAwait.js

//📒05_asyncAwait.js - 방법1
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 키워드를 이용해 작성합니다
  const user1 = await getDataFromFilePromise(user1Path);
  const user2 = await getDataFromFilePromise(user2Path);
  const result = JSON.parse(`[${user1}, ${user2}]`);
  return result;
};

readAllUsersAsyncAwait();

module.exports = {
  readAllUsersAsyncAwait,
};
더보기

 추가 방법2와 방법3

//📒05_asyncAwait.js - 방법2
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 키워드를 이용해 작성합니다
  const user1 = await getDataFromFilePromise(user1Path);
  const user2 = await getDataFromFilePromise(user2Path);
  return [JSON.parse(user1), JSON.parse(user2)];
};

// readAllUsersAsyncAwait();

module.exports = {
  readAllUsersAsyncAwait,
};
//📒05_asyncAwait.js - 방법3(코드스테이츠 레퍼런스)
const { join } = require("path");
const { getDataFromFilePromise } = require("./02_promiseConstructor");

const user1Path = join(__dirname, "files/user1.json");
const user2Path = join(__dirname, "files/user2.json");
//__dirname : 현재실행중인 폴더

const readAllUsersAsyncAwait = async () => {
  const json = await Promise.all([
    getDataFromFilePromise(user1Path),
    getDataFromFilePromise(user2Path),
  ]).then((texts) => texts.map((text) => JSON.parse(text)));
  return json;
};
//---
let data1 = await getDataFromFilePromise(user1Path);
let data2 = await getDataFromFilePromise(user2Path);
let result = [];
result.push(JSON.parse(data1));
result.push(JSON.parse(data2));
return result;
// readAllUsersAsyncAwait();

module.exports = {
  readAllUsersAsyncAwait,
};

3rd-party 모듈을 사용하는 방법

공식적으로 제공하는 빌트인 모듈(built-in module)이 아닌 외부모듈을 써드파티모듈이라함

예) Node.js에서 `underscore`는 Node.js공식문서에 없는 모듈이기 때문에 써드ㅋㅋ

`underscore`을 사용하고싶다면

npm을 사용해설치. `npm install underscore`

써드파티모듈불러오기 `const _ = require('underscore')`


Q. `Promise.all`의 인자는 어떠한 형태인가?  -  array

/** 
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>;

Q. `Promise.all`을 사용할 경우 `then`메소드의 파라미터는 어떠한 형태인가?

Promise.all은 인자로 배열을 받는데, 배열의 요소는 Promise이다.

 

/**

* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
Comments