이번 포스트에서는 비동기 작업을 처리하는 몇 가지 방법을 소개하도록 하겠다. 아마 비동기 시리즈의 마지막 포스트가 될 것 같다.
이전 시간까지는 주로 비동기 작업의 순서를 보장하는 방법에 대해서 이야기했었다.
그런데 어떤 경우에는 작업들간의 순서는 중요하지 않고, 단순히 작업들을 빨리 처리하는게 중요할 수 있다.
작업들을 빨리 처리하려면, 여러가지 작업을 한 번에 실행하면 된다.
비동기 작업은 메인 스레드에서 실행되는 것이 아니라 worker thread pool에서 실행되는 작업이기 때문에 동시에 여러가지 작업을 처리하는 것이 가능하다.
코드를 보며 설명해보겠다.
우리는 work(1), work(2), work(3)을 해야한다.
작업이 끝나는 순서나 시작되는 순서는 상관이 없고, 오로지 세 가지일을 빨리 끝내는것이 중요하다.
const work = (num) => (new Promise((resolve) => {
setTimeout(() => resolve(num), num * 100)
}))
async function doWork() {
const start = Date.now()
await work(1)
await work(2)
await work(3)
console.log(`time = ${Date.now() - start}`) // 600
}
doWork()
위의 코드를 실행하면, 3가지의 일을 모두 끝내는데 걸리는 시간은 0.6초이다. 왜냐하면, 1이 끝나야 2가 시작하고 2가 끝나야 3이 시작하기 때문이다.
어떻게 비동기 작업을 동시에 실행하는지 방법을 소개하겠다.
const work = (num) => (new Promise((resolve) => {
setTimeout(() => resolve(num), num * 100)
}))
async function doWorkP() {
const start = Date.now()
await Promise.all([work(1), work(2), work(3)])
console.log(`Parallel = ${Date.now() - start}`) // 300
}
doWorkP()
이렇게 Promise.all([ ])을 사용하면 동시에 비동기 작업들을 수행할 수 있다.
추가로 return하는 resolve 값도 배열 [ ]이다.
+) Promise.race( )
여러 작업들 중 가장 먼저 끝난 것을 리턴하고 다음으로 넘어간다.
async function doWorkR() {
const start = Date.now()
const winner = await Promise.race([work(1), work(2), work(3)])
console.log(`Race = ${Date.now() - start}, winner = ${winner}`) // Race = 101, winner = 1
}
+) Promise.allSettled( )
Promise.all의 한계는 동시에 실행되는 여러 작업들 중 하나라도 rejcet되는 경우가 있으면 실패한다는 점이다.
그래서 ES2020에서 Promise.allSettled가 도입되었다.
const work = (num) => (new Promise((resolve) => {
setTimeout(() => resolve(num), num * 100)
}))
const failWork = new Promise((resolve, reject) => reject('fail'))
async function doWorkP() {
const start = Date.now()
await Promise.all([work(1), work(2), work(3), failWork])
console.log(`Parallel = ${Date.now() - start}`)
}
doWorkP() // failWork 때문에 실패한다.
async function doWorkP2() {
const start = Date.now()
await Promise.allSettled([work(1), work(2), work(3), failWork])
console.log(`Parallel = ${Date.now() - start}`)
}
doWorkP2() // failWork를 제외한 다른 resolve 값만 가지고 다음으로 진행한다.
이번 포스트를 끝으로 자바스크립트 비동기 프로그래밍 시리즈를 마무리하겠다.