프로그램 개발서

JavaScript Array.fromAsync()로 비동기 반복값을 순서대로 배열로 만들기 본문

Javascript

JavaScript Array.fromAsync()로 비동기 반복값을 순서대로 배열로 만들기

rairen 2026. 8. 7. 06:57

문제와 사용 상황

async generator나 Node.js 스트림처럼 비동기적으로 값을 내보내는 입력을 배열로 모을 때 for await...ofPromise.all()을 상황별로 나누어 사용하게 됩니다. Array.fromAsync()는 async iterable, 일반 iterable, array-like 입력을 배열로 만들고 mapper 결과도 await합니다.

반환값은 배열 자체가 아니라 배열로 이행되는 Promise입니다. 따라서 await가 필요합니다. 모든 작업을 동시에 시작할 목적이면 순차적으로 값을 기다리는 Array.fromAsync() 대신 Promise.all()을 선택해야 합니다.

테스트 환경·버전·날짜

2026-08-06 KST에 외부 패키지 없이 Node.js v24.14.0에서 실행했고, Node.js v23.11.1에서도 같은 테스트를 반복했습니다.

최소 재현 코드

async function* numbers() {
  yield 1;
  yield 2;
  yield 3;
}

const values = await Array.fromAsync(numbers());
console.log(values); // [1, 2, 3]

const doubled = await Array.fromAsync(
  numbers(),
  async (value, index) => value * 2 + index
);
console.log(doubled); // [2, 5, 8]

일반 iterable에 Promise가 들어 있는 경우에도 각 값을 기다립니다.

const labels = await Array.fromAsync([
  Promise.resolve("first"),
  Promise.resolve("second")
]);
console.log(labels); // ["first", "second"]

테스트 케이스와 결과

케이스 실제 출력 결과
메서드 지원 function 통과
async iterable + mapper [2, 5, 8] 통과
Promise 값 [first, second] 통과
array-like [x, y] 통과
mapper 예외 Error: mapper failure 통과

두 Node.js 버전에서 모든 케이스가 allPass=true였습니다.

최종 코드

export async function collectUsers(userSource) {
  return Array.fromAsync(
    userSource,
    async (user, index) => ({
      index,
      id: user.id,
      name: user.name.trim()
    })
  );
}

async function* readUsers() {
  yield { id: 10, name: "  Mina " };
  yield { id: 20, name: "Joon" };
}

const users = await collectUsers(readUsers());
console.log(users);
// 순차 수집
const ordered = await Array.fromAsync(source);

// 독립 작업의 동시 처리
const concurrent = await Promise.all(promises);

실패 조건·브라우저·버전 차이

  • 반환값은 Promise이므로 await 없이 배열 메서드를 호출할 수 없습니다.
  • mapper 예외나 rejection은 전체 결과 Promise를 거부합니다.
  • Array.fromAsync()는 값을 하나씩 await하므로 Promise.all()과 동시성이 다릅니다.
  • async iterable의 구현에 따라 mapper에 전달되는 값의 형태가 달라질 수 있어 입력 프로토콜을 확인해야 합니다.
  • 이번 실행은 Node.js v24.14.0과 v23.11.1만 확인했습니다. 다른 브라우저 결과는 별도 테스트가 필요합니다.

보안·호환성 주의사항

큰 스트림이나 끝나지 않는 입력을 모두 배열화하면 메모리가 커질 수 있습니다. 입력 개수와 항목 크기를 제한하고 필요하면 for await...of로 스트리밍 처리하세요. mapper 안에서 사용자 입력을 SQL·셸·HTML에 이어 붙이지 말고 대상별 검증과 인코딩을 적용합니다. 브라우저 분기는 사용자 에이전트 문자열 대신 typeof Array.fromAsync === "function" 같은 기능 검사로 처리합니다.

직접 확인 방법

  1. typeof Array.fromAsync를 실행해 function인지 확인합니다.
  2. async generator를 await Array.fromAsync()에 전달해 배열을 확인합니다.
  3. Promise 배열과 비동기 mapper를 넣어 Promise가 남지 않는지 확인합니다.
  4. mapper에서 오류를 던져 예외 처리가 동작하는지 확인합니다.
  5. 큰 입력은 메모리와 처리 지연을 측정하고 무제한 배열화를 피합니다.

공식 참고자료

변경 이력

2026-08-06: async iterable, Promise 값, array-like, mapper 오류를 두 Node.js 버전에서 실행하고 Promise.all()과의 순차·동시 처리 차이를 정리했습니다.

반응형