GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add code examples · HowProgrammingWorks/WebStreams@c11fcd8

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • JavaScript
    • 1-readable.js
    • 2-transform.js
    • 3-pipe.js
    • 4-backpressure.js
    • 5-tee.js
    • 6-cancel.js
    • 7-pull.js
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎JavaScript/1-readable.js‎

Copy file name to clipboard
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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

‎JavaScript/2-transform.js‎

Copy file name to clipboard
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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

‎JavaScript/3-pipe.js‎

Copy file name to clipboard
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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

‎JavaScript/4-backpressure.js‎

Copy file name to clipboard
+39Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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

‎JavaScript/5-tee.js‎

Copy file name to clipboard
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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

‎JavaScript/6-cancel.js‎

Copy file name to clipboard
+40Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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

‎JavaScript/7-pull.js‎

Copy file name to clipboard
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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();

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.