mirror of
https://github.com/withastro/astro.git
synced 2025-01-27 22:19:04 -05:00
Fix streaming in Node.js fast path (#11058)
* Fix streaming in Node.js fast path * Create a new next if the iterator is not done * Use a flag instead * Update test * Add new assertion * Add explanation of the renderingComplete variable * Remove flaky assertion
This commit is contained in:
parent
00420a7a52
commit
749a7ac967
3 changed files with 22 additions and 7 deletions
5
.changeset/fluffy-pears-press.md
Normal file
5
.changeset/fluffy-pears-press.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
Fix streaming in Node.js fast path
|
|
@ -209,14 +209,23 @@ export async function renderToAsyncIterable(
|
|||
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 = promiseWithResolvers<void>();
|
||||
let next: ReturnType<typeof promiseWithResolvers<void>> | null = null;
|
||||
const buffer: Uint8Array[] = []; // []Uint8Array
|
||||
let renderingComplete = false;
|
||||
|
||||
const iterator: AsyncIterator<Uint8Array> = {
|
||||
async next() {
|
||||
if (result.cancelled) return { done: true, value: undefined };
|
||||
|
||||
await next.promise;
|
||||
if(next !== null) {
|
||||
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) {
|
||||
|
@ -276,8 +285,7 @@ export async function renderToAsyncIterable(
|
|||
// Push the chunks into the buffer and resolve the promise so that next()
|
||||
// will run.
|
||||
buffer.push(bytes);
|
||||
next.resolve();
|
||||
next = promiseWithResolvers<void>();
|
||||
next?.resolve();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -286,12 +294,14 @@ export async function renderToAsyncIterable(
|
|||
renderPromise
|
||||
.then(() => {
|
||||
// Once rendering is complete, calling resolve() allows the iterator to finish running.
|
||||
next.resolve();
|
||||
renderingComplete = true;
|
||||
next?.resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
// If an error occurs, save it in the scope so that we throw it when next() is called.
|
||||
error = err;
|
||||
next.resolve();
|
||||
renderingComplete = true;
|
||||
next?.resolve();
|
||||
});
|
||||
|
||||
// This is the Iterator protocol, an object with a `Symbol.asyncIterator`
|
||||
|
|
|
@ -37,7 +37,7 @@ describe('Streaming', () => {
|
|||
let chunk = decoder.decode(bytes);
|
||||
chunks.push(chunk);
|
||||
}
|
||||
assert.equal(chunks.length > 1, true);
|
||||
assert.equal(chunks.length > 5, true);
|
||||
});
|
||||
|
||||
it('Body of slots is chunked', async () => {
|
||||
|
|
Loading…
Add table
Reference in a new issue