일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 기초 수학
- nodejs
- mariadb
- rabbitmq
- For
- Backbone.js
- docker
- CentOS
- SQL
- deep learning
- AWS
- javascript
- python
- Babel
- Redis
- nginx
- Node
- Go
- linux
- React
- webpack
- php
- Machine Learning
- Switch
- laravel
- phpredis
- 블레이드 템플릿
- NCP
- Redux
- fastapi
- Today
- Total
개발일기
Javascript - Promise.all, async await 비동기 작업 본문
자바스크립트에서 비동기 작업을 처리하기 위해 주로 사용되는 방법은 Promise.all과 Async Await다.
Promise.all
Promise.all은 비동기로 실행할 여러 개의 Promise 객체를 배열에 넣어서 병렬로 실행한다.
const promise1 = setTimeout(() => {
console.log('Start Promise1')
}, 2000) // 2초 후 실행(setTimeout)
const promise2 = setTimeout(() => {
console.log('Start Promies2')
}, 1000) // 1초 후 실행(setTimeout)
// Promise.all 배열에 비동기로 실행한 작업들을 추가
Promise.all([promise1, promise2]).then(() => {
console.log('res') // success then
}).catch((err) => {
console.log('Error:', err) // catch error
})
/*
Start Promise2
Start Promise1
*/
promise1과 promise2를 비동기로 실행하기 위해 Promise.all()배열에 추가하였다. 이 두 작업은 병렬로 실행되는데 여기서 병렬이란 순차의 반대말이다.
- 순차 실행(Sequential): promise1 작업이 끝난 후, promise2가 실행되는 방식을 의미한다.
- 병렬 실행(Parallel): promise1 작업의 종료 여부와 상관없이 promise2를 거의 동시에 시작하는 방식을 의미한다.
만약 Promise.all이 순차 실행이라면 코드가 실행된 후 ‘Start Promise1’이 2초 후에 찍히고 ‘Start Promise2’가 3초 후에 찍혀야 한다. 하지만 병렬 실행이기 때문에 ‘Start Promie2’가 1초 후에 찍히고 ‘Start Promise1’이 2초 후에 찍히는 것을 확인할 수 있다. 즉, 순차로 실행하면 3초가 소요되는 작업을 2초 만에 끝낼 수 있다.
이렇게 보면 Promise.all이 더 좋아 보이지만 Promise.all은 모든 객체가 성공적으로 실행되어야 then() 함수가 실행된다. promise1과 promise2 둘 중 하나가 실행에 실패하면 catch()로 이동한다. 객체의 성공과 실패 여부는 resolve()와 reject()로 구분한다.
- resolve(): 함수의 실행이 성공했을 때 반환할 값을 넣는다.
- reject(): 함수 실행이 실패했을 때 반환할 값을 넣는다.
const promise1 = new Promise((resolve, reject) => {
// new Promise() 생성자 안에 코드 작성
setTimeout(() => {
resolve('success1') // resolve
}, 2000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success2') // resolve
}, 1000)
})
Promise.all([promise1, promise2]).then((promiseRes) => {
console.log('promiseRes: ', promiseRes)
}).catch((err) => {
console.error('Error:', err)
})
// promiseRes: [ 'success1', 'success2' ]
promise1과 promise2 작업에서 resolve, reject를 사용하려면 new Promise() 생성자 안에 코드를 작성해야 한다. 각각의 작업이 성공했다고 가정하고 resolve()에 적당한 값을 넣어 반환한다. 두 작업이 모두 성공했기에 then부분이 실행된다. 이와 반대로 두 작업 중 하나가 실패했다고 가정을 하면 catch부분이 실행된다. Promise.all은 모든 작업이 성공해야 then이 반환되기 때문에 하나라도 실패하면 catch가 실행된다.
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success1') // resolve
}, 2000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('success2') // reject -> catch 실행
}, 1000)
})
Promise.all([promise1, promise2]).then((promiseRes) => {
console.log('promiseRes: ', promiseRes)
}).catch((err) => {
console.error('Error:', err)
})
promise2 부분에 일부로 reject()가 반환되도록 하였으며 이로 인해 catch가 실행된다.
- then(): Promise.all의 작업이 모두 성공했을 때, 실행되는 부분이다. resolve()로 반환되는 값이 있으면 위와 같이 then() 파라미터에 변수를 대입하여 resolve값을 then()에서 확인할 수 있다.
- catch(): Promise.all의 작업이 하나라도 실패했을 때, 실행되는 부분이다. then과 마찬가지로 catch() 파라미터에 변수를 대입하여 reject값을 catch()에서 확인할 수 있다.
async await
async await는 비동기 함수라는 것을 나타내는 async 함수 안에 await를 나열하여 비동기 작업을 처리한다.
const asyncFunc = async () => {
await async1()
.then((asyncRes) => {
console.log(asyncRes)
}).catch((err) => {
console.log('err: ', err)
})
await async2()
.then((asyncRes) => {
console.log(asyncRes)
}).catch((err) => {
console.log('err: '. err)
})
}
function async1() {
// Promise 반환
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success1')
}, 2000);
})
}
function async2() {
// Promise 반환
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success2')
}, 1000)
})
}
asyncFunc()
// success1
// success2
Promise.all과 다르게 async1()이 먼저 실행된 후, async2()가 뒤이어 실행된다. async await는 순차적으로 비동기 작업이 실행되기 때문에 await의 순서에 따라 실행된다.
reject() 에러 처리
Promise.all과 async await가 각각 병렬, 순차 실행이라는 특징 외에도 reject() 에러 처리하는 방법 또한 다르다.
function async2() {
// Promise 반환
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('failure2')
}, 1000)
})
}
// undefined 출력
Promise.all에서 한 것과 동일하게 async2함수를 resolve대신 reject로 에러 처리를 하도록 변경한 후 실행하면 async2() 부분은 undefined가 출력된다. async await에서는 reject가 발생하면 then의 두 번째 콜백에서 reject가 처리된다.
await async2()
.then((asyncRes) => {
console.log(asyncRes)
}, (err) => {
console.log('then reject: ', err) // reject 처리
}).catch((err) => {
console.log('reject: '. err)
})
// then reject: failure2
위와 같이 then()의 두 번째 콜백에서 reject를 처리할 수 있게 코드를 작성하면 reject가 정상적으로 출력되는 것을 확인할 수 있다.
reject() 에러 처리가 다른 이유
Promise.all과 async await의 reject() 에러 처리 부분이 다른 이유는 Promise.all은 비동기 작업이 하나라도 reject되면 전체가 실패로 간주되기 때문에 catch() 가 실행된다. 하지만 async await는 비동기 작업 중 하나에서 reject가 되더라도 실패로 간주하지 않기 때문에 catch() 부분이 실행되지 않는다.
참고 사이트:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://stackoverflow.com/questions/55328177/how-to-manually-trigger-a-reject-in-async-await
'Javascript' 카테고리의 다른 글
Javascript - Date() 시간에 대하여 (0) | 2021.11.22 |
---|---|
Javascript의 AMD, CommonJS 모듈화 (0) | 2021.11.17 |
Babel - es5로 변환하는 기초 예제 (0) | 2021.10.05 |
Webpack의 구성요소 (0) | 2021.10.03 |
Webpack 설명 및 예제 (0) | 2021.10.03 |