비동기(callback,Promise,Async&await)

0

node.js

목록 보기
1/5
post-thumbnail

동기와 비동기가 있습니다.
먼저 동기는 순차적으로 일을 처리 하는것입니다.
비동기는 일처리를 하면서 동시다발적으로 각각 일을 처리 하는것입니다.

위에 그림에서 보면 첫번째 그림은 동기적인 처리 입니다.
첫번째 일을 서버에 넘기고 응답이 오면 다음 일을 처리합니다.

반면에 두번째 그림에서는 클라이언트가 서버에 동시에 일을 보내고 일이 끝나는 순서대로 응답을 받습니다.

동기와 비동기의 차이를 크게 말하면 이렇게 말할 수 있습니다.
우리가 대부분 코딩하는 로직은 동기적으로 실행됩니다.

오늘은 비동기의 대해서 자세히 알아가봅시다. !

1. callback

간단히 콜백은 다른 함수가 실행을 끝낸뒤 실행되는 함수입니다.
자세히 말하면 어떤 함수에 인자로 쓰여지는 함수입니다.

const getDataFromFile = function (filePath, callback) {
  fs.readFile(filePath,'utf8',(err, data)=>{
    if(err){
      callback(err,null);
    }else{
      callback(err,data);
    }
  }) 
};

파일을 읽어오는 메소드를 사용하는 방법은
fs.readFile(filename, [options], callback); 이다.
fs.readFile은 node.js내장 모듈이다.
내장모듈에는 여러가지가 있다.
여기를참고해보세요

콜백함수는 쓰다보면 콜백지옥 현상이 옵니다. 이것을 방지 하기 위해 비동기에 두가지를 더 배워 봅시다.

2. Promise

Promise는 프로미스가 생성될 때 꼭 알 수 있지는 않은 값을 위한 대리자로, 비동기 연산이 종료된 이후의 결과값이나 실패 이유를 처리하기 위한 처리기를 연결할 수 있도록 합니다.

대기(pending): 이행하거나 거부되지 않은 초기 상태.
이행(fulfilled): 연산이 성공적으로 완료됨.
거부(rejected): 연산이 실패함.

- 생성자 Promise()

const promise1 = new Promise((resolve, reject) => {
	setTimeout(()=> {
    	resolve('foo')
    },300)
})

- 메서드

1 - Promise.all(iterable)
.all 메서드는 여러 프로미스의 결과를 모을 때 유용합니다

2 - Promise.race(iterable)
iterable 내의 어떤 프로미스가 이행하거나 거부하는 즉시 스스로 이행하거나 거부하는 프로미스를 반환합니다. 이행 값이나 거부 이유는 원 프로미스의 값이나 이유를 그대로 사용합니다.

3 - Promise.reject()
주어진 이유로 거부하는 Promise 객체를 반환합니다.

4 - Promise.resolve()
주어진 값으로 이행하는 Promise 객체를 반환합니다.

Promise 프로토타입

1 - Promise.prototype.catch()
에러를 잡아 반환한다
2 - Promise.prototype.then()
성공적인 값을 받아 반환한다.
3 - Promise.prototype.finally()
마지막으로 실행할값을 받아 반환한다.

const getDataFromFilePromise = filePath => {
  return new Promise((resolve,reject) =>{//Promise생성 매개변수에 resolve,reject 넣어주기
    fs.readFile(filePath, 'utf8',(err, data)=>{
      if(err){
        reject(err);// 에러가 났을땐 reject함수가 에러값 반환
      }else{
        resolve(data);// 성공시엔 resolve함수가 데이터값 반환
      }
  })
  }) 
};

callback 함수로 작성 해본 소스를 Promise로 재작성 하였습니다.
resolve는 성공적인 값을 반환 하고 reject는 에러가 발생시 에러를 반환 합니다.

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

const readAllUsersChaining = () => {
  return getDataFromFilePromise(user1path)
  .then(user1 =>{//.then으로 연결 정상적인 값만 반환 user1에user1path값이 들어 있다.
    return getDataFromFilePromise(user2path)
    .then(user2 =>{//user2에 user2path 값이 들어있다.
		return `[${user1},${user2}]`    
    })
  })
  .then(data => JSON.parse(data)) // 문자열을 객체화 시켜주기위해 
}

.then 으로 정상적인 값만 반환 한다.

const readAllUsers = () => {
  return Promise.all([
    getDataFromFilePromise(user1Path),
    getDataFromFilePromise(user2Path)
  ])
  .then(([user1,user2]) =>{
    return `[${user1},${user2}]`
  })
  .then(data => JSON.parse(data));
}

Promise.all을 이용하여 한번에 프로미스를 불러올수있다.

3. async & await

자바스크립트의 비동기 처리 패턴 중 가장 최근에 나온 문법입니다.
기존의 비동기 처리 방식인 콜백 함수와 프로미스의 단점을 보완하고 개발자가 읽기 좋은 코드를 작성할 수 있게 도와줍니다.

암시적으로 promise를 사용하여 결과를 반환합니다.
그러나 비동기 함수를 하용하는 코드의 구문과 구조는 표준동기 함수를 사용하는것과 많이 비슷합니다.

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

 const readAllUsersAsyncAwait = async() => {
    let user1 = await getDataFromFilePromise(user1Path);
    let user2 = await getDataFromFilePromise(user2Path);
    let data = `[${user1},${user2}]`;
 	return JSON.parse(data);
}

함수 앞에 async를 붙여줘야한다.
await를 앞에 붙여 프로미스값을 가져온다.

profile
👩🏻‍💻항상발전하자 🔥

3개의 댓글

comment-user-thumbnail
2020년 11월 10일

너무 멋져요

1개의 답글
comment-user-thumbnail
2020년 11월 10일

정말 정리가 잘된것 같아요 잘보고 갑니다!!

답글 달기