Skip to content

Commit

Permalink
Move onCompleteAll to .allReady Promise
Browse files Browse the repository at this point in the history
The onCompleteAll callback can sometimes resolve before the promise that
returns the stream which is tough to coordinate. A more idiomatic API
for a one shot event is a Promise.

That way the way you render for SEO or SSG is:

const stream = await renderToReadableStream(...);
await stream.readyAll;
respondWith(stream);

Ideally this should be a sub-class of ReadableStream but we don't yet
compile these to ES6 and they'd had to be to native class to subclass
a native stream.

I have other ideas for overriding the .tee() method in a subclass anyway.
So this is inline with that strategy.
  • Loading branch information
sebmarkbage committed Mar 3, 2022
1 parent 05c283c commit dbd968b
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,10 @@ describe('ReactDOMFizzServer', () => {
<Wait />
</Suspense>
</div>,
{
onCompleteAll() {
isComplete = true;
},
},
);

stream.allReady.then(() => (isComplete = true));

await jest.runAllTimers();
expect(isComplete).toBe(false);
// Resolve the loading.
Expand Down
19 changes: 15 additions & 4 deletions packages/react-dom/src/server/ReactDOMFizzServerBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,34 @@ type Options = {|
bootstrapModules?: Array<string>,
progressiveChunkSize?: number,
signal?: AbortSignal,
onCompleteAll?: () => void,
onError?: (error: mixed) => void,
|};

// TODO: Move to sub-classing ReadableStream.
type ReactDOMServerReadableStream = ReadableStream & {
allReady: Promise<void>,
};

function renderToReadableStream(
children: ReactNodeList,
options?: Options,
): Promise<ReadableStream> {
): Promise<ReactDOMServerReadableStream> {
return new Promise((resolve, reject) => {
let onCompleteAll;
const allReady = new Promise(resolve => {
onCompleteAll = resolve;
});

function onCompleteShell() {
const stream = new ReadableStream({
const stream: ReactDOMServerReadableStream = new ReadableStream({
type: 'bytes',
pull(controller) {
startFlowing(request, controller);
},
cancel(reason) {},
});
// TODO: Move to sub-classing ReadableStream.
stream.allReady = allReady;
resolve(stream);
}
function onErrorShell(error: mixed) {
Expand All @@ -66,7 +77,7 @@ function renderToReadableStream(
createRootFormatContext(options ? options.namespaceURI : undefined),
options ? options.progressiveChunkSize : undefined,
options ? options.onError : undefined,
options ? options.onCompleteAll : undefined,
onCompleteAll,
onCompleteShell,
onErrorShell,
);
Expand Down

0 comments on commit dbd968b

Please sign in to comment.