-
-
Save jakearchibald/d0b7e65496a8ec362f10739c3e28da6e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function mergeResponses(responsePromises, headers) { | |
const readers = responsePromises.map(p => Promise.resolve(p).then(r => r.body.getReader())); | |
let doneResolve; | |
let doneReject; | |
const done = new Promise((r, rr) => { | |
doneResolve = r; | |
doneReject = rr; | |
}); | |
const readable = new ReadableStream({ | |
async pull(controller) { | |
const reader = await readers[0]; | |
try { | |
const {done, value} = await reader.read(); | |
if (done) { | |
readers.shift(); | |
if (!readers[0]) { | |
controller.close(); | |
doneResolve(); | |
return; | |
} | |
return this.pull(controller); | |
} | |
controller.enqueue(value); | |
} | |
catch (err) { | |
doneReject(err); | |
throw err; | |
} | |
}, | |
cancel() { | |
doneResolve(); | |
} | |
}); | |
const response = await responsePromises[0]; | |
return { | |
done, | |
response: new Response(readable, { | |
headers: headers || response.headers | |
}) | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This depends on transform streams & async iterators | |
async function mergeResponses(responsePromises, headers) { | |
const {readable, writable} = new TransformStream(); | |
const done = (async function() { | |
for await (const response of responsePromises) { | |
await response.body.pipeTo(writable, {preventClose: true}); | |
} | |
writable.getWriter().close(); | |
})(); | |
return { | |
done, | |
response: new Response(readable, { | |
headers: headers || (await responsePromises[0]).headers | |
}) | |
}; | |
} |
Ah, well spotted!
can you explain why use promises here?
const readers = responsePromises.map(p => Promise.resolve(p).then(r => r.body.getReader()));
instead of using simple array?
const readers = responsePromises.map(p => p.body.getReader()
@PRMSA it allows responsePromises
to be a mix of Promise<Response>
and plain Response
.
future2.js
const mergeResponses = async (
responsePromises = [Promise.resolve(new Response())],
headers = new Headers()
) => new Response(new ReadableStream({ async start(controller) {
for await (const response of responsePromises) {
// Bonus example: controller.enqueue(await response.text());
await response.body.pipeTo(new WritableStream({
write: (data) => controller.enqueue(data)
}));
}
}}),{
headers: headers.has("Content-Type") ? headers : (await responsePromises[0]).headers
});
// usage example
globalThis.onfetch = (event) => event.respondWith(mergeResponses([...responsePromises]));
The function parameters got set with empty default values for typeInferencing in IDE's
so the above example is 100% Typed
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Maybe a couple of bugs in this? Not sure if you can do a PR to a gist, but I had to change these:
Line 27:
Line 41:
Thanks for writing this. Very useful for a demo I'm doing for a talk this weekend!