동시성 처리
concurrent는 여러 비동기 값을 한 번에 처리할 수 있는 함수입니다.
JavaScript에는 Promise.all로 여러 promise 값을 동시에 평가하는 함수가 있습니다. 그러나 동시 요청의 부하를 처리할 수 없고 무한한 열거 가능한 데이터 집합에 대한 요청을 처리할 수 없습니다. concurrent는 무한 데이터 집합의 비동기 요청을 처리하고 부하의 요청 크기를 제어할 수 있습니다.
ts
// prettier-ignore
import { pipe, toAsync, range, map, filter, take, each, concurrent } from "@fxts/core";
const fetchApi = (page) =>
new Promise((resolve) => setTimeout(() => resolve(page), 1000));
await pipe(
range(Infinity),
toAsync,
map(fetchApi), // 0,1,2,3,4,5
filter((a) => a % 2 === 0),
take(3), // 0,2,4
concurrent(3), // 이 줄이 없으면 총 6초가 걸립니다.
each(console.log), // 2초
);하나씩 요청할 때 6초가 걸리지만 concurrent를 사용하면 2초가 걸리는 것을 확인할 수 있습니다.
유용한 예제
더 실용적인 코드는 아래와 같습니다.
위 코드에서 concurrent의 위치가 아래와 같다면, 결과가 달라질까요? 아닙니다, 동일합니다! concurrent는 항상 길이가 변경되기 전의 Iterable에 적용된다는 점에 유의하세요.
ts
await pipe(
range(Infinity),
toAsync,
map(fetchApi),
concurrent(3),
filter((a) => a % 2 === 0),
take(3),
each(console.log),
);map까지 순차적으로 하나씩 평가하고, filter의 비동기 predicate를 세 개씩 동시에 평가하고 싶다면, 아래 코드를 작성해야 합니다:
ts
await pipe(
range(Infinity),
toAsync,
map(fetchApi),
toArray,
filter((a) => delay(100, a % 2 === 0)),
take(3),
concurrent(3),
each(console.log),
);