Openstatus www.openstatus.dev
at 4c0f4c00a38753a5d0dfd7e7b7b7706dec6f1503 77 lines 2.1 kB view raw
1export async function* yieldMany(promises: Promise<unknown>[]) { 2 // Attach .then() handlers to the promises to remove them as soon as they resolve 3 // biome-ignore lint/complexity/noForEach: REMINDER: do not use for await (const p of promises) as it will not work as expected 4 promises.forEach((p) => { 5 p.then((value) => { 6 promises.splice(promises.indexOf(p), 1); 7 return value; 8 }); 9 }); 10 11 // Continue yielding the results of the promises as they resolve 12 while (promises.length > 0) { 13 yield await Promise.race(promises); 14 } 15 16 return "done"; 17} 18 19export function iteratorToStream(iterator: AsyncGenerator) { 20 return new ReadableStream({ 21 async pull(controller) { 22 try { 23 const { value, done } = await iterator.next(); 24 if (done) { 25 controller.close(); 26 } else { 27 controller.enqueue(value); 28 } 29 } catch (err) { 30 console.error("Stream error:", err); 31 controller.error(err); 32 } 33 }, 34 }); 35} 36 37const encoder = new TextEncoder(); 38const decoder = new TextDecoder(); 39 40/** 41 * HOW TO USE IT IN YOUR ROUTE 42 * @returns {Response} 43 */ 44export async function POST(request: Request) { 45 // extract your params from the request 46 const _json = await request.json(); 47 48 const generator = yieldMany([ 49 new Promise((resolve) => 50 setTimeout(() => resolve(encoder.encode("1")), 200), 51 ), 52 new Promise((resolve) => resolve(encoder.encode("2"))), 53 new Promise((resolve) => 54 setTimeout(() => resolve(encoder.encode("3")), 500), 55 ), 56 ]); 57 58 const stream = iteratorToStream(generator); 59 return new Response(stream); 60} 61 62/** 63 * HOW TO USE IT IN YOUR CLIENT 64 */ 65async function clientConsumeStream() { 66 const response = await POST(new Request("")); // fetch("/api/path/to/route", { method: "POST" }); 67 const reader = response.body?.getReader(); 68 if (!reader) return; 69 70 while (true) { 71 const { value, done } = await reader.read(); 72 if (done) break; 73 console.log("Stream output:", decoder.decode(value)); 74 } 75 76 console.log("Stream processing complete."); 77}