UNPKG

@mui/internal-docs-infra

Version:

MUI Infra - internal documentation creation tools.

85 lines (83 loc) 2.72 kB
/** A snapshot emitted by {@link streamChunks} after each chunk lands. */ /** * Drive any {@link StreamSource} `mode` and yield an accumulating snapshot after * each chunk lands. Isomorphic: the client (`useStream`) iterates it and * `setState`s each snapshot for progressive reveal; the server awaits it to * completion for non-incremental modes. * * - `'data'` - one `load`, one terminal snapshot. * - `'urls'` - `loadUrls`, then `loadChunk` per URL, one snapshot each; the * final URL is the last chunk unless `loadUrls` returned `lastChunk: false`. * - `'stream'` - runs the generator (which pushes into the array and yields), * surfacing a snapshot per yield, then a terminal snapshot on return. * * Stops early (without a terminal snapshot) if `signal` aborts. */ export async function* streamChunks(source, options, signal) { if (source.mode === 'data') { const data = await source.load(options, signal); if (signal.aborted) { return; } yield { chunks: [data], lastChunk: true }; return; } if (source.mode === 'urls') { const result = await source.loadUrls(options, signal); if (signal.aborted) { return; } const urls = result.chunks; const accumulated = []; for (let index = 0; index < urls.length; index += 1) { // Sequential by design: chunks stream in and yield in order for // progressive reveal - loading in parallel would defeat that. // eslint-disable-next-line no-await-in-loop const data = await source.loadChunk(urls[index], options, signal); if (signal.aborted) { return; } accumulated.push(data); const isLast = index === urls.length - 1 && result.lastChunk !== false; yield { chunks: [...accumulated], lastChunk: isLast }; } if (urls.length === 0) { // Nothing to load - still signal completion so a controller can settle. yield { chunks: [], lastChunk: result.lastChunk !== false }; } return; } // stream mode: the generator pushes into `accumulated` and yields after each. const accumulated = []; const generator = source.stream(accumulated, options, signal); let step = await generator.next(); while (!step.done) { if (signal.aborted) { return; } yield { chunks: [...accumulated], lastChunk: false }; // Sequential by design: a generator is driven one step at a time. // eslint-disable-next-line no-await-in-loop step = await generator.next(); } if (signal.aborted) { return; } // Generator returned -> the stream is complete. yield { chunks: [...accumulated], lastChunk: true }; }