코딩

[JS / Node] 비동기

Frontend 2022. 5. 31. 23:37

키워드 : 비동기, callback, Promise, Promise chaining, Promise All, Async Await


비동기의 순차 제어 방법

- 기본적으로 비동기의 경우, 작업이 순차적으로 시작되었다고 해서 결과도 순차적으로 나오지 않음.

- 순어를 제어하고 싶을 경우 : callback 함수, Promise, Async Await 활용.

 

 

1. callback 함수

- 함수 내에서 callback 함수를 계속해서 호출하여 순서를 제어할 수 있다.

- 하지만, callback 함수가 대량으로 끊임없이 이어질 경우 일명 'callback hell'이 발생.

 

예시 코드)

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

 


 

2. Promise

- callback hell을 피할 수 있는 방안으로서 등장.

- callback을 연이어 쓰는 것보다 Promise를 이용하는 것이 가독성이 더 좋다.

- Promise는 class에 해당한다 -> 따라서 생성시 'new Promise()'로 만들어줘야 한다.

- 구조 : 매개변수로 2개의 콜백함수, 즉 executor 함수(resolve, reject)를 지닌다.

  • resolve : 함수의 결과가 성공했을 때, 뒤에 나오는 .then()으로 전달된 콜백함수가 호출된다.
  • reject : 함수의 결과가 실패했을 때, 뒤에 나오는 .catch()로 전달된 콜백함수가 호출된다. 

- 매서드 :

  • then() : 함수의 결과가 성공하면 호출됨. then 자체는 promise를 리턴. 
  • catch() : 함수의 결과가 실패하면 호출됨. 

- Promise의 3가지 status :

  • pending : 대기열에 들어간 상태.
  • fulfilled : 올바르게 이행된 상태.
  • rejected : 거절된 상태.

예시 코드)

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

 

 Promise chaining : promise hell을 방지하기 위한 것으로서, then으로 연결시켜 직관성을 높여준다.

예시 코드)

const readAllUsersChaining = () => {
return getDataFromFilePromise(user1Path).then(user1 => {
   return getDataFromFilePromise(user2Path).then(user2 => {
     return [JSON.parse(user1), JSON.parse(user2)]
   })
 })
 }

 

Promise.all

예시 코드)

const readAllUsers = () => {
  return Promise.all([getDataFromFilePromise(user1Path), getDataFromFilePromise(user2Path)])
  .then(values => [JSON.parse(values[0]), JSON.parse(values[1])]);
}

Reference)

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

 

Promise.all() - JavaScript | MDN

Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환합니다. 주어진 프로미스 중 하나가 거부하는 경우, 첫

developer.mozilla.org

 


 

3. Async await

- promise보다 더 가독성이 높은 코드 방식.

- promise hell 방지가 가능하다.

- 함수명 앞에 async를 붙여주고, promise 값 앞에 await를 붙여준다.

 

예시 코드)

onst readAllUsersAsyncAwait = async () => {
    let user1 = await getDataFromFilePromise(user1Path)
    let user2 = await getDataFromFilePromise(user2Path)
    return [JSON.parse(user1), JSON.parse(user2)]
}

 


결론은,

callback  < promise < async await 순으로

가독성 비교가 가능하다.