From 18d330b16330d76c4b2991839c6b4462d5a4163f Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Mon, 6 Mar 2023 16:57:50 +0100 Subject: [PATCH] fix: deal with fast consecutive promise resolutions when streaming (#9332) * fix: deal with fast consecutive promise resolutions when streaming fixes #9330 * Update packages/kit/src/utils/streaming.js --- .changeset/strange-garlics-pump.md | 5 +++++ packages/kit/src/utils/streaming.js | 17 ++++++++++++----- packages/kit/src/utils/streaming.spec.js | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 .changeset/strange-garlics-pump.md create mode 100644 packages/kit/src/utils/streaming.spec.js diff --git a/.changeset/strange-garlics-pump.md b/.changeset/strange-garlics-pump.md new file mode 100644 index 000000000000..54207bbc4e41 --- /dev/null +++ b/.changeset/strange-garlics-pump.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: deal with fast consecutive promise resolutions when streaming diff --git a/packages/kit/src/utils/streaming.js b/packages/kit/src/utils/streaming.js index f5fcce837c1d..1015231f46b8 100644 --- a/packages/kit/src/utils/streaming.js +++ b/packages/kit/src/utils/streaming.js @@ -23,22 +23,29 @@ function defer() { * }} */ export function create_async_iterator() { - let deferred = defer(); + let deferred = [defer()]; return { iterator: { [Symbol.asyncIterator]() { return { - next: () => deferred.promise + next: async () => { + const next = await deferred[0].promise; + if (!next.done) deferred.shift(); + return next; + } }; } }, push: (value) => { - deferred.fulfil({ value, done: false }); - deferred = defer(); + deferred[deferred.length - 1].fulfil({ + value, + done: false + }); + deferred.push(defer()); }, done: () => { - deferred.fulfil({ done: true }); + deferred[deferred.length - 1].fulfil({ done: true }); } }; } diff --git a/packages/kit/src/utils/streaming.spec.js b/packages/kit/src/utils/streaming.spec.js new file mode 100644 index 000000000000..ccee5a99fa87 --- /dev/null +++ b/packages/kit/src/utils/streaming.spec.js @@ -0,0 +1,20 @@ +import { test } from 'uvu'; +import * as assert from 'uvu/assert'; +import { create_async_iterator } from './streaming.js'; + +test(`works with fast consecutive promise resolutions`, async () => { + const iterator = create_async_iterator(); + + Promise.resolve(1).then((n) => iterator.push(n)); + Promise.resolve(2).then((n) => iterator.push(n)); + Promise.resolve().then(() => iterator.done()); + + const actual = []; + for await (const value of iterator.iterator) { + actual.push(value); + } + + assert.equal(actual, [1, 2]); +}); + +test.run();