Iterator Helpers의 지연 평가

조기 종료를 take에 위임하면 필요한 만큼만 fetch 한다. 페이지네이션 API에서 “조건에 맞는 N개”만 필요할 때. sync 는 네이티브(모던 브라우저·Node 22+), async 는 제안(Stage 2)이라 core-js 폴리필.

import 'core-js/proposals/async-iterator-helpers.js'

type Page<T> = { items: T[]; next: string | null }

/** 커서 페이지네이션 API 를 순회한다 — 현재 페이지를 다 당긴 뒤에야 다음 페이지를 받는다. */
async function* fetchPages<T>(url: string | null): AsyncGenerator<T> {
  while (url) {
    const { items, next }: Page<T> = await fetch(url).then((r) => r.json())
    yield* items
    url = next
  }
}

await AsyncIterator.from(fetchPages<Item>('/api/items')).filter(isValid).take(10).toArray()

toArray 가 next() 로 당길 때만 take → filter → fetchPages 순으로 계산이 거슬러 올라가고, 아이템은 fetchPages → filter(isValid) → take(10) → toArray 로 흐른다. fetchPages 는 현재 페이지를 다 당긴 뒤에야 다음 페이지를 요청한다. 예를 들어 10개가 2페이지에서 차면 take 가 끝나며 return() 이 filter 를 거쳐 fetchPages 까지 거슬러 올라가 소스를 닫는다 — finally 가 돌아 연결·커서를 정리하고, 3페이지는 요청되지 않는다. 요청 수를 세면 확인된다. for await 에서 break 해도 같은 return() 이 일어난다.

  • 제안이 개정 중이다 — 동시 next() 동작이 미정이라 폴리필과 다를 수 있다. 순차로 당기는 toArray엔 영향 없음.
  • TS 타입이 없다 — TS 5.8 lib·core-js 어디에도 AsyncIterator.from 선언이 없어 직접 선언한다.

출처

#564