C.W.K.
Stream
Lesson 03 of 05 · published

Async Iterable: `for await`

~9 min · async-promises, async-iterable, for-await, streaming

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"값마다 Promise. Type system 이 이해하는 stream."

Async iterable 이 뭐

Async iterable 이 `async next(): Promise<{ value: T; done: boolean }>` method 있는 object 반환하는 [Symbol.asyncIterator]() method 가진 object. for await (const x of stream) 가 그걸 walk, 각 값 await 한 후 계속.

이게 Node.js stream, file line iterator, HTTP-server request body 가 타입 붙는 법. 시간이 지나 도착하는 일련의 값 있는 어디든 async iterable 이 canonical 모양.

Promise yield 하는 generator

Async iterable 만드는 가장 쉬운 방법이 async generator: async function* gen(): AsyncIterable { yield 1; yield 2; yield await fetchValue() }. 각 `yield` 가 stream 의 한 값 만듦; generator 안 await 가 값 준비될 때까지 pause.

Promise 와의 차이

`Promise` 가 전체 배열로 resolve 하는 한 Promise. `AsyncIterable` 가 stream — 값이 한 번에 하나씩 도착, 마지막 도착 전 첫 거 처리 시작 가능. 큰 데이터나 느린 producer 엔 async iterable 이 stream 가능하게; 작은 batch 데이터엔 Promise 가 더 단순.

Async iterable 이 stream 의 type-system handle. 값이 시간이 지나 도착하면 `AsyncIterable` 와 `for await` 손 뻗어. 모든 값이 함께 도착하면 `Promise` 손 뻗어.

Code

Async iterable — generator 와 Node stream·typescript
// Async generator — 시간이 지나 값 yield.
async function* tickStream(): AsyncIterable<number> {
  for (let i = 0; i < 5; i++) {
    await new Promise((r) => setTimeout(r, 100));
    yield i;
  }
}

// for-await 로 소비.
async function consume() {
  for await (const n of tickStream()) {
    console.log(n);    // n: number, 100ms 마다 출력
  }
}

// fs stream, Node 의 readline, fetch 의 body — 다 async iterable.
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';

async function readLines(path: string) {
  const rl = createInterface({ input: createReadStream(path) });
  for await (const line of rl) {
    console.log(line);   // line: string
  }
}

External links

Exercise

next 가 null 일 때까지 연속 page 에서 item yield 하는 async generator paginate<T>(fetchPage: (cursor: string | null) => Promise<{ items: T[]; next: string | null }>): AsyncIterable<T> 써. 그다음 for await 로 소비.
Hint
각 iteration: fetchPage(currentCursor) await, 각 item yield, .next 에서 currentCursor update. next 가 null 이면 멈춤. Consumer 가 pagination 절대 안 봄 — 그냥 item 의 stream.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.