Skip to content
File

Blob: samples/web-streams/streams-util.js

javascript142 lines
1// Copyright (c) 2017-2024 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5// Future work: Additional stream patterns to demonstrate
6// - Tee: Split a stream with readable.tee()
7// - Chained transforms: Multiple TransformStreams piped together
8// - Built-in streams: CompressionStream, TextEncoderStream/TextDecoderStream
9// - Request body consumption: Pipe incoming POST body through transforms
10// - BYOB reading: Demonstrate "bring your own buffer" with byte streams
11 
12// Sample words for generating lorem ipsum-style text
13const WORDS = [
14 "lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit",
15 "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore",
16 "magna", "aliqua", "enim", "ad", "minim", "veniam", "quis", "nostrud",
17 "exercitation", "ullamco", "laboris", "nisi", "aliquip", "ex", "ea", "commodo",
18 "consequat", "duis", "aute", "irure", "in", "reprehenderit", "voluptate",
19 "velit", "esse", "cillum", "fugiat", "nulla", "pariatur", "excepteur", "sint",
20 "occaecat", "cupidatat", "non", "proident", "sunt", "culpa", "qui", "officia",
21 "deserunt", "mollit", "anim", "id", "est", "laborum"
22];
23 
24const enc = new TextEncoder();
25 
26function generateChunk() {
27 const wordsPerChunk = 50 + Math.floor(Math.random() * 50);
28 const words = [];
29 for (let i = 0; i < wordsPerChunk; i++) {
30 words.push(WORDS[Math.floor(Math.random() * WORDS.length)]);
31 }
32 return enc.encode(words.join(" ") + "\n\n");
33}
34 
35// Creates a ReadableStream that generates random lorem ipsum-style text synchronously
36export function createSyncLoremStream(numChunks) {
37 let chunksRemaining = numChunks;
38 
39 return new ReadableStream({
40 pull(controller) {
41 if (chunksRemaining <= 0) {
42 controller.close();
43 return;
44 }
45 controller.enqueue(generateChunk());
46 chunksRemaining--;
47 }
48 }, { highWaterMark: 16 });
49}
50 
51// Creates a ReadableStream that generates random lorem ipsum-style text asynchronously
52export function createAsyncLoremStream(numChunks) {
53 let chunksRemaining = numChunks;
54 
55 return new ReadableStream({
56 async pull(controller) {
57 if (chunksRemaining <= 0) {
58 controller.close();
59 return;
60 }
61 await scheduler.wait(10);
62 controller.enqueue(generateChunk());
63 chunksRemaining--;
64 }
65 }, { highWaterMark: 16 });
66}
67 
68// Creates a byte ReadableStream that generates random lorem ipsum-style text synchronously
69export function createSyncLoremByteStream(numChunks) {
70 let chunksRemaining = numChunks;
71 
72 return new ReadableStream({
73 type: "bytes",
74 pull(controller) {
75 if (chunksRemaining <= 0) {
76 controller.close();
77 return;
78 }
79 controller.enqueue(generateChunk());
80 chunksRemaining--;
81 }
82 }, { highWaterMark: 16 * 1024 });
83}
84 
85// Creates a byte ReadableStream that generates random lorem ipsum-style text asynchronously
86export function createAsyncLoremByteStream(numChunks) {
87 let chunksRemaining = numChunks;
88 
89 return new ReadableStream({
90 type: "bytes",
91 async pull(controller) {
92 if (chunksRemaining <= 0) {
93 controller.close();
94 return;
95 }
96 await scheduler.wait(10);
97 controller.enqueue(generateChunk());
98 chunksRemaining--;
99 }
100 }, { highWaterMark: 16 * 1024 });
101}
102 
103// Creates a TransformStream that converts text to uppercase synchronously
104export function createSyncUppercaseTransform() {
105 const decoder = new TextDecoder();
106 const encoder = new TextEncoder();
107 
108 return new TransformStream({
109 transform(chunk, controller) {
110 const text = decoder.decode(chunk, { stream: true });
111 controller.enqueue(encoder.encode(text.toUpperCase()));
112 },
113 flush(controller) {
114 const remaining = decoder.decode();
115 if (remaining) {
116 controller.enqueue(encoder.encode(remaining.toUpperCase()));
117 }
118 }
119 });
120}
121 
122// Creates a TransformStream that converts text to uppercase asynchronously
123export function createAsyncUppercaseTransform() {
124 const decoder = new TextDecoder();
125 const encoder = new TextEncoder();
126 
127 return new TransformStream({
128 async transform(chunk, controller) {
129 await scheduler.wait(10);
130 const text = decoder.decode(chunk, { stream: true });
131 controller.enqueue(encoder.encode(text.toUpperCase()));
132 },
133 async flush(controller) {
134 await scheduler.wait(10);
135 const remaining = decoder.decode();
136 if (remaining) {
137 controller.enqueue(encoder.encode(remaining.toUpperCase()));
138 }
139 }
140 });
141}