GeezerVison is showing github.com — Add code examples · HowProgrammingWorks/WebStreams@c11fcd8
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboard +26Lines changed: 26 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const fromIterable = (iterable) => | | 4 | + new ReadableStream({ | | 5 | + start(controller) { | | 6 | + for (const value of iterable) { | | 7 | + controller.enqueue(value); | | 8 | + } | | 9 | + controller.close(); | | 10 | + }, | | 11 | + }); | | 12 | + | | 13 | +// Usage | | 14 | + | | 15 | +const main = async () => { | | 16 | + const stream = fromIterable(['a', 'b', 'c', 'd']); | | 17 | + const reader = stream.getReader(); | | 18 | + | | 19 | + while (true) { | | 20 | + const { done, value } = await reader.read(); | | 21 | + if (done) break; | | 22 | + console.log('chunk:', value); | | 23 | + } | | 24 | +}; | | 25 | + | | 26 | +main(); |
Collapse file Copy file name to clipboard +29Lines changed: 29 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const upper = new TransformStream({ | | 4 | + transform(chunk, controller) { | | 5 | + controller.enqueue(String(chunk).toUpperCase()); | | 6 | + }, | | 7 | +}); | | 8 | + | | 9 | +const source = new ReadableStream({ | | 10 | + start(controller) { | | 11 | + for (const word of ['web', 'streams', 'transform']) { | | 12 | + controller.enqueue(word); | | 13 | + } | | 14 | + controller.close(); | | 15 | + }, | | 16 | +}); | | 17 | + | | 18 | +// Usage | | 19 | + | | 20 | +const main = async () => { | | 21 | + const reader = source.pipeThrough(upper).getReader(); | | 22 | + while (true) { | | 23 | + const { done, value } = await reader.read(); | | 24 | + if (done) break; | | 25 | + console.log(value); | | 26 | + } | | 27 | +}; | | 28 | + | | 29 | +main(); |
Collapse file Copy file name to clipboard +27Lines changed: 27 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const source = new ReadableStream({ | | 4 | + start(controller) { | | 5 | + controller.enqueue(new TextEncoder().encode('line 1\n')); | | 6 | + controller.enqueue(new TextEncoder().encode('line 2\n')); | | 7 | + controller.close(); | | 8 | + }, | | 9 | +}); | | 10 | + | | 11 | +const chunks = []; | | 12 | + | | 13 | +const sink = new WritableStream({ | | 14 | + write(chunk) { | | 15 | + chunks.push(Buffer.from(chunk).toString()); | | 16 | + console.log('write:', Buffer.from(chunk).toString().trim()); | | 17 | + }, | | 18 | + close() { | | 19 | + console.log('writable closed'); | | 20 | + }, | | 21 | +}); | | 22 | + | | 23 | +// Usage | | 24 | + | | 25 | +source.pipeTo(sink).then(() => { | | 26 | + console.log('piped:', chunks.join('')); | | 27 | +}); |
Collapse file Copy file name to clipboard +39Lines changed: 39 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +// Explicit backpressure: slow consumer → desiredSize drops → producer waits. | | 4 | + | | 5 | +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); | | 6 | + | | 7 | +const slowSink = new WritableStream( | | 8 | + { | | 9 | + async write(chunk) { | | 10 | + console.log('sinking', chunk, 'at', Date.now() % 100000); | | 11 | + await sleep(100); | | 12 | + }, | | 13 | + }, | | 14 | + { highWaterMark: 1 }, | | 15 | +); | | 16 | + | | 17 | +const producer = new ReadableStream( | | 18 | + { | | 19 | + async start(controller) { | | 20 | + for (let i = 0; i < 5; i++) { | | 21 | + // Pipe buffer full → desiredSize <= 0 → wait before enqueue | | 22 | + while (controller.desiredSize !== null && controller.desiredSize <= 0) { | | 23 | + console.log('backpressure: desiredSize', controller.desiredSize); | | 24 | + await sleep(20); | | 25 | + } | | 26 | + console.log('enqueue', i, 'desiredSize:', controller.desiredSize); | | 27 | + controller.enqueue(i); | | 28 | + } | | 29 | + controller.close(); | | 30 | + }, | | 31 | + }, | | 32 | + { highWaterMark: 1 }, | | 33 | +); | | 34 | + | | 35 | +// Usage | | 36 | + | | 37 | +producer.pipeTo(slowSink).then(() => { | | 38 | + console.log('done (producer paced itself via desiredSize)'); | | 39 | +}); |
Collapse file Copy file name to clipboard +25Lines changed: 25 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const source = new ReadableStream({ | | 4 | + start(controller) { | | 5 | + for (let i = 1; i <= 4; i++) controller.enqueue(i); | | 6 | + controller.close(); | | 7 | + }, | | 8 | +}); | | 9 | + | | 10 | +const [left, right] = source.tee(); | | 11 | + | | 12 | +const readAll = async (name, stream) => { | | 13 | + const reader = stream.getReader(); | | 14 | + const values = []; | | 15 | + while (true) { | | 16 | + const { done, value } = await reader.read(); | | 17 | + if (done) break; | | 18 | + values.push(value); | | 19 | + } | | 20 | + console.log(name, values); | | 21 | +}; | | 22 | + | | 23 | +// Usage | | 24 | + | | 25 | +Promise.all([readAll('left', left), readAll('right', right)]); |
Collapse file Copy file name to clipboard +40Lines changed: 40 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); | | 4 | + | | 5 | +const source = new ReadableStream({ | | 6 | + async start(controller) { | | 7 | + for (let i = 0; i < 10; i++) { | | 8 | + if (controller.desiredSize === null) return; | | 9 | + console.log('produce', i); | | 10 | + try { | | 11 | + controller.enqueue(i); | | 12 | + } catch { | | 13 | + console.log('producer stopped after cancel'); | | 14 | + return; | | 15 | + } | | 16 | + await sleep(40); | | 17 | + } | | 18 | + try { | | 19 | + controller.close(); | | 20 | + } catch { | | 21 | + // already cancelled | | 22 | + } | | 23 | + }, | | 24 | + cancel(reason) { | | 25 | + console.log('cancel reason:', reason); | | 26 | + }, | | 27 | +}); | | 28 | + | | 29 | +// Usage | | 30 | + | | 31 | +const main = async () => { | | 32 | + const reader = source.getReader(); | | 33 | + const first = await reader.read(); | | 34 | + console.log('got', first.value); | | 35 | + await reader.cancel('consumer done early'); | | 36 | + const after = await reader.read(); | | 37 | + console.log('after cancel:', after); | | 38 | +}; | | 39 | + | | 40 | +main(); |
Collapse file Copy file name to clipboard +29Lines changed: 29 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +// Pull-based ReadableStream: data produced only when the consumer reads | | 4 | + | | 5 | +const countStream = (max) => { | | 6 | + let n = 0; | | 7 | + return new ReadableStream({ | | 8 | + pull(controller) { | | 9 | + n += 1; | | 10 | + console.log('pull produced', n); | | 11 | + controller.enqueue(n); | | 12 | + if (n >= max) controller.close(); | | 13 | + }, | | 14 | + }); | | 15 | +}; | | 16 | + | | 17 | +// Usage | | 18 | + | | 19 | +const main = async () => { | | 20 | + const reader = countStream(3).getReader(); | | 21 | + console.log('reader created (no pull yet)'); | | 22 | + while (true) { | | 23 | + const { done, value } = await reader.read(); | | 24 | + if (done) break; | | 25 | + console.log('got', value); | | 26 | + } | | 27 | +}; | | 28 | + | | 29 | +main(); |
|