본문 바로가기

코드스테이츠 immersive

Server Side Techniques 에 대해서

여러번의 비동기 함수로 인한 충돌을 방지하기 위해서 만들어진것이 바로 promise 라는 것입니다.

Promise는 여러 번의 asynchronous call로 인해 callback이 중첩되는 상황에서 여러분의 수고를 덜어줄 수 있는 유용한 도구입니다.

Promise는 Asynchronous libraries에서 기본적으로 사용하기 시작했고 ES6에서는 language standard로 포함되어 있습니다. 

Promise를 사용하기에 앞서서 연결되는 개념들을 여러가지 알아보도록 하겠습니다.

첫번째로 콜백 함수를 이용한 파일 시스템 사용과 request 사용을 적어보겠습니다.

파일시스템

1
2
3
4
5
6
7
8
9
10
11
const getDataFromFile = function(filePath, callback) {//filePath 파일 위치 , callback 함수..
  fs.readFile(filePath,"utf-8",function aa(err,data){
    if(err){ //에러가 있을 경우에
      callback(err,null); //에러가 있을경우 에러 메세지 와 null을 출력한다
    }
    else{
      callback(err,data.split("\n")) //에러가 있을 경우 에러메세지 와 없을경우 data.split("\n")을 입력한다.
    }
  })
 
};
cs

request 

1
2
3
4
5
6
7
8
9
10
const getBodyFromGetRequest = function(url, callback) { //url 과 callback 함수
  request(url,function(err,response,body){ 
      if(err){ //에러메세지가 있을경우
        callback(err,null); //에러메세지가 있을경우 err 없을 경우 null출력
      }
      else//에러가 있을경우
        callback(err,JSON.parse(body))
      }
  })
};
cs

두번째로 promise를 생성해서 만드는 법을 만들어 보겠습니다.

파일시스템

1
2
3
4
5
6
7
8
9
10
11
12
const getDataFromFilePromise = filePath => {
  return new Promise(function(reslove, reject){ //promise 는 resolve 와 reject를 나눠서 만든다.
    fs.readFile(filePath,"utf-8",function (err,data){
      if(err){
        reject(err);
      }
      else{
        reslove(data.split("\n"))
      }
    })
  })
};
cs

request

1
2
3
4
5
6
7
8
9
10
11
12
const getBodyFromGetRequestPromise = url => {
  return new Promise(function(reslove,reject){
    request(url,function(err,response,body){
       if(err){
         reject(err)
       }
       else{
         reslove(JSON.parse(body))
       }
    })
  })
};
cs

함수를 promise 형태로 바꾸는 것.

1
2
3
const getDataFromFilePromise = util.promisify(getDataFromFile)
 
const getBodyFromGetRequestPromise = util.promisify(getBodyFromGetRequest)
cs

npm util을 이용해서 util.promisify에 함수를 넣으면 promise 타입으로 바꾼다.

 

promise를 이용한 값을 가져와서 핸들링하는 법.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const BASE_URL = "https://koreanjson.com/users/";
 
const fetchUsersAndWriteToFile = (readFilePath, writeFilePath) => {
  let newPromise =  getDataFromFilePromise(readFilePath) //파일을 읽어온다
         .then(Ids => Ids.map(id => BASE_URL+id)) //읽어온 id값마다 url를 더해서 보내줄 url형식을 맞춘다.
         .then(id => id.map(id => getBodyFromGetRequestPromise(id))) // request요청을 보내는 promise타입에 가져온 url를 넣는다.
         .then(pend => Promise.all(pend)) //요청했던 정보가 돌아오도록 기다려야 한다.... 모든 promise 묶어서 요청을 가져올떄까지 기다린다.
      return newPromise.then(arr => arr.map(obj => obj.name)) //각 객체마다 name 객체부터 추출해 낸다.
         .then(namearr => namearr.map(name => name +"\n")) // 배열을 각 이름을 엔터키로 더한다 
         .then(names => names.join(""))//각이름을 다 묶는다.
         .then(names => writeFilePromise(writeFilePath,names)) //write타입의 promise 객체를 가지오와서 파라미터 갑을 넣늗다.
    
 
};
cs

await를 사용한 핸들링

 

1
2
3
4
5
6
7
8
9
10
11
12
13
 
const BASE_URL = "https://koreanjson.com/users/";
 
const fetchUsersAndWriteToFileAsync = async (readFilePath, writeFilePath) => {
     const data1 = await getDataFromFilePromise(readFilePath)  //파일경로에서 값을 읽어오는 promise 를 실행한다.
     const data2 =  data1.map(id=> BASE_URL+id) //가져온 id값들을 가지고 rquest 요청할 url를 만든다 그리고 만들어놓은 rquest 요청하는 promise 함수를 가지고 대입을 해서 실행한다.
    .map(id=>getBodyFromGetRequestPromise(id)) 
     const data3 = await Promise.all(data2)
     const data4 = await data3.map(data => data.name).map(name => name+"\n").join("")
     const data5 = await  writeFilePromise(writeFilePath,data4)
     return data5
     
};
cs