Skip to content

Proposal: yieldSame for async generators #778

@aralroca

Description

@aralroca

When we do HTML streaming, currently, async generators are the last ones to control the chunks better and render streaming lists incrementally (see example). But if we want to show a title with the number of elements rendered in the list, which is updated in streaming, it is currently impossible to do easily.

import { Database } from "bun:sqlite";

const db = new Database("db.sqlite");

export default function MovieList() {
  return (
   <>
      <h2>Number of movies: {/* ??? */}</h2>
      <ul>
        <MovieItems />
      </ul>
   </>
  );
}

// Streaming HTML from SQLite query
async function* MovieItems() {
  for (const movie of db.query("SELECT title, year FROM movies")) {
    yield (
      <li>
        {movie.title} ({movie.year})
      </li>
    );
  }
}

Proposal: Add the yieldSame API to allow for the modification of the same chunk each time instead of increasing the number of chunks.

Example:

import { Database } from "bun:sqlite";

const db = new Database("db.sqlite");

export default function MovieList() {
  const movies = db.query("SELECT title, year FROM movies");

  return (
   <>
      <Title movies={movies} />
      <ul>
        <MovieItems movies={movies} />
      </ul>
   </>
  );
}

async function* Title({ movies }) {
  let i = 0;

  for (const movie of movies) {
    yield (
      <h2>
        Number of movies {++i}
      </h2>
    );
  }
}

// Modifying same chunk in Streaming HTML
Title.yieldSame = true;

// Streaming HTML from SQLite query
async function* MovieItems({ movies }) {
  for (const movie of movies) {
    yield (
      <li>
        {movie.title} ({movie.year})
      </li>
    );
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions