[JS / Node] 비동기
키워드 : 비동기, 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 순으로
가독성 비교가 가능하다.