A server method that's a generator can send its output as it's made, which suits text that takes a while, such as a reply from a language model.
use Unscripted\Ui\{Component, Server, State};
new class extends Component {
#[State] public string $topic = '';
public string $story = '';
#[Server]
public static function write(string $topic): Generator
{
foreach (Story::about($topic) as $chunk) { // your own source of chunks
yield $chunk;
}
return 'done';
}
public function tell(): Generator
{
$this->story = '';
$result = yield static::write($this->topic)->into('story');
}
};
<input u-model="topic"> <button u-on:click="tell">Tell me a story</button>
<p>{{ $story }}</p>
->into('story')appends each chunk to$storyas it arrives, rendering each time.- The
yieldgets the method's return value when it's done, or the whole text if it returns nothing. - Over HTTP the browser gets one JSON line per chunk (
application/x-ndjson), as they're yielded. - Over the WebSocket transport, and in tests, the method runs to the end first and the text arrives all at once.
- Without
->into(), the method is run through and the result is its return value, or the chunks joined.