Home / Function/ renderToAsyncIterable() — astro Function Reference

renderToAsyncIterable() — astro Function Reference

Architecture documentation for the renderToAsyncIterable() function in render.ts from the astro codebase.

Entity Profile

Dependency Diagram

graph TD
  a4540b08_b256_31dc_609c_62af4c628a44["renderToAsyncIterable()"]
  e0446a2c_f6ef_c306_3fa2_3d3016b94419["render.ts"]
  a4540b08_b256_31dc_609c_62af4c628a44 -->|defined in| e0446a2c_f6ef_c306_3fa2_3d3016b94419
  531bf937_76da_4b29_be5c_c5f57d933834["callComponentAsTemplateResultOrResponse()"]
  a4540b08_b256_31dc_609c_62af4c628a44 -->|calls| 531bf937_76da_4b29_be5c_c5f57d933834
  a3bddb01_2167_e26f_7cb4_0806d1960ddd["bufferHeadContent()"]
  a4540b08_b256_31dc_609c_62af4c628a44 -->|calls| a3bddb01_2167_e26f_7cb4_0806d1960ddd
  b4ab2273_2885_6a1f_2a1c_274c7b025334["toPromise()"]
  a4540b08_b256_31dc_609c_62af4c628a44 -->|calls| b4ab2273_2885_6a1f_2a1c_274c7b025334
  style a4540b08_b256_31dc_609c_62af4c628a44 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

packages/astro/src/runtime/server/render/astro/render.ts lines 207–374

export async function renderToAsyncIterable(
	result: SSRResult,
	componentFactory: AstroComponentFactory,
	props: any,
	children: any,
	isPage = false,
	route?: RouteData,
): Promise<AsyncIterable<Uint8Array> | Response> {
	const templateResult = await callComponentAsTemplateResultOrResponse(
		result,
		componentFactory,
		props,
		children,
		route,
	);
	if (templateResult instanceof Response) return templateResult;
	let renderedFirstPageChunk = false;
	if (isPage) {
		await bufferHeadContent(result);
	}

	// This implements the iterator protocol:
	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols
	// The `iterator` is passed to the Response as a stream-like thing.
	// The `buffer` array acts like a buffer. During render the `destination` pushes
	// chunks of Uint8Arrays into the buffer. The response calls `next()` and we combine
	// all of the chunks into one Uint8Array and then empty it.

	let error: Error | null = null;
	// The `next` is an object `{ promise, resolve, reject }` that we use to wait
	// for chunks to be pushed into the buffer.
	let next: ReturnType<typeof promiseWithResolvers<void>> | null = null;
	const buffer: Array<Uint8Array | string> = []; // []Uint8Array
	let renderingComplete = false;

	const iterator: AsyncIterator<Uint8Array> = {
		async next() {
			if (result.cancelled) return { done: true, value: undefined };

			if (next !== null) {
				await next.promise;
			}
			// Buffer is empty so there's nothing to receive, wait for the next resolve.
			else if (!renderingComplete && !buffer.length) {
				next = promiseWithResolvers();
				await next.promise;
			}

			// Only create a new promise if rendering is still ongoing. Otherwise
			// there will be a dangling promises that breaks tests (probably not an actual app)
			if (!renderingComplete) {
				next = promiseWithResolvers();
			}

			// If an error occurs during rendering, throw the error as we cannot proceed.
			if (error) {
				throw error;
			}

			// This calculates the length of the final merged array.
			// While doing so, it also replaces consecutive strings with their
			// concatenated Uint8Array equivalent.
			// This is a performance optimization since `TextEncoder#encode` can be
			// costly, so it is faster to encode one larger string than it is
			// to encode many smaller strings.
			let length = 0;
			let stringToEncode = '';
			for (let i = 0, len = buffer.length; i < len; i++) {
				const bufferEntry = buffer[i];

				if (typeof bufferEntry === 'string') {
					const nextIsString = i + 1 < len && typeof buffer[i + 1] === 'string';
					stringToEncode += bufferEntry;
					if (!nextIsString) {
						const encoded = encoder.encode(stringToEncode);
						length += encoded.length;
						stringToEncode = '';
						buffer[i] = encoded;
					} else {
						buffer[i] = '';
					}

Domain

Subdomains

Frequently Asked Questions

What does renderToAsyncIterable() do?
renderToAsyncIterable() is a function in the astro codebase, defined in packages/astro/src/runtime/server/render/astro/render.ts.
Where is renderToAsyncIterable() defined?
renderToAsyncIterable() is defined in packages/astro/src/runtime/server/render/astro/render.ts at line 207.
What does renderToAsyncIterable() call?
renderToAsyncIterable() calls 3 function(s): bufferHeadContent, callComponentAsTemplateResultOrResponse, toPromise.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free