Skip to content

Instantly share code, notes, and snippets.

@jakearchibald
Last active January 4, 2023 13:33
Embed
What would you like to do?
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 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
})
};
}
@triblondon
Copy link

triblondon commented May 31, 2017

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:

controller.enqueue(value);

Line 41:

return {
  done,
  response: new Response(readable, {
    headers: headers || response.headers
  })
};

Thanks for writing this. Very useful for a demo I'm doing for a talk this weekend!

@jakearchibald
Copy link
Author

Ah, well spotted!

@PRMSA
Copy link

PRMSA commented Dec 26, 2022

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()

@jakearchibald
Copy link
Author

@PRMSA it allows responsePromises to be a mix of Promise<Response> and plain Response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment