Streaming with ReadableStream and WritableStream in Deno
📖 Scenario: You are building a simple data pipeline in Deno that reads text data from a source, processes it, and writes it to a destination using streams.This simulates real-world tasks like reading files, transforming data, and saving results efficiently without loading everything into memory.
🎯 Goal: Create a small Deno program that uses ReadableStream to provide data, a configuration variable to control chunk size, a TransformStream to convert text to uppercase, and a WritableStream to collect and output the transformed data.
📋 What You'll Learn
Create a ReadableStream that emits three text chunks: 'hello', ' ', and 'world'.
Add a configuration variable chunkSize set to 5.
Use a TransformStream to convert all text chunks to uppercase.
Create a WritableStream that collects all chunks into a single string variable result.
💡 Why This Matters
🌍 Real World
Streaming data efficiently is important in web servers, file processing, and real-time applications to handle large data without blocking or using too much memory.
💼 Career
Understanding streams and how to transform and pipe data is a key skill for backend developers, especially when working with modern JavaScript runtimes like Deno or Node.js.
Progress0 / 4 steps
1
Create a ReadableStream with text chunks
Create a ReadableStream called sourceStream that emits the exact text chunks 'hello', ' ', and 'world' in sequence.
Deno
Hint
Use new ReadableStream with a start(controller) method. Use controller.enqueue() to send chunks and controller.close() when done.
2
Add a chunk size configuration variable
Add a constant variable called chunkSize and set it to the number 5.
Deno
Hint
Simply declare const chunkSize = 5; below the stream.
3
Create a TransformStream to uppercase text
Create a TransformStream called upperCaseTransform that converts each incoming text chunk to uppercase and passes it on.
Deno
Hint
Use new TransformStream with a transform(chunk, controller) method that calls controller.enqueue(chunk.toUpperCase()).
4
Create a WritableStream to collect output
Create a WritableStream called destinationStream that collects all chunks into a variable result (initially empty string). Append each chunk to result in the write(chunk) method.
Deno
Hint
Declare let result = ''; and create new WritableStream with a write(chunk) method that appends chunk to result.
Practice
(1/5)
1. What is the main purpose of a ReadableStream in Deno?
easy
A. To accept data chunks that can be written
B. To produce data chunks that can be read
C. To store data permanently
D. To convert data into JSON format
Solution
Step 1: Understand the role of ReadableStream
A ReadableStream is designed to produce data chunks that can be read by consumers.
Step 2: Differentiate from WritableStream
A WritableStream accepts data chunks to be written, which is the opposite role.
Final Answer:
To produce data chunks that can be read -> Option B
Quick Check:
ReadableStream produces data = A [OK]
Hint: ReadableStream produces data; WritableStream consumes data [OK]
Common Mistakes:
Confusing ReadableStream with WritableStream
Thinking streams store data permanently
Assuming streams convert data formats automatically
2. Which of the following is the correct way to create a new WritableStream in Deno?
easy
A. const stream = new WritableStream({ write(chunk) { console.log(chunk); } });
B. const stream = WritableStream.write(chunk => console.log(chunk));
C. const stream = new WritableStream.write(chunk => console.log(chunk));
D. const stream = WritableStream({ write(chunk) { console.log(chunk); } });
Solution
Step 1: Recall WritableStream constructor syntax
WritableStream is created with new WritableStream() and an object with a write method.
Step 2: Check each option's syntax
const stream = new WritableStream({ write(chunk) { console.log(chunk); } }); correctly uses new WritableStream({ write(chunk) { ... } }). Others misuse syntax or omit new.
Final Answer:
const stream = new WritableStream({ write(chunk) { console.log(chunk); } }); -> Option A
Quick Check:
WritableStream needs new + write method object = C [OK]
Hint: Use 'new WritableStream' with an object having a write method [OK]
Common Mistakes:
Omitting 'new' keyword
Calling WritableStream as a function
Passing a function directly instead of an object
3. What will the following code output in Deno?
const readable = new ReadableStream({
start(controller) {
controller.enqueue('Hello');
controller.enqueue('World');
controller.close();
}
});
const reader = readable.getReader();
(async () => {
let result = '';
while(true) {
const { done, value } = await reader.read();
if (done) break;
result += value + ' ';
}
console.log(result.trim());
})();
medium
A. Error: reader.read is not a function
B. HelloWorld
C. Hello World
D. undefined
Solution
Step 1: Understand the ReadableStream setup
The stream enqueues two chunks: 'Hello' and 'World', then closes.
Step 2: Analyze the reading loop
The loop reads each chunk, appends it with a space to result, and stops when done is true.
Step 3: Output after trimming
After reading both chunks, result is 'Hello World ' which trims to 'Hello World'.
Final Answer:
Hello World -> Option C
Quick Check:
Chunks read and concatenated with space = D [OK]
Hint: ReadableStream chunks read sequentially, concatenated with spaces [OK]
Common Mistakes:
Forgetting to await reader.read()
Not trimming the final string
Assuming chunks concatenate without spaces
4. Identify the error in this Deno code using streams:
The write method calls chunk.toUpperCase(), which only works on strings.
Step 2: Analyze the write call argument
The code writes the number 123, which has no toUpperCase() method, causing a runtime error.
Final Answer:
Cannot call toUpperCase on a number -> Option D
Quick Check:
toUpperCase on number causes error = A [OK]
Hint: Check data types before calling string methods [OK]
Common Mistakes:
Assuming write must be async
Thinking getWriter() is invalid
Missing await on WritableStream creation
5. You want to transform a ReadableStream of text chunks to uppercase and write them to a WritableStream. Which approach correctly implements this in Deno?
hard
A. Pipe the readable through a TransformStream that uppercases chunks, then pipe to writable
B. Directly write chunks from readable to writable without transformation
C. Use readable.getReader() and writable.getWriter(), but forget to release locks
D. Convert chunks to uppercase after writing to writable
Solution
Step 1: Understand stream transformation
To modify data between readable and writable, use a TransformStream that changes chunks to uppercase.
Step 2: Use pipeThrough and pipeTo methods
Pipe the readable stream through the transform, then pipe the result to the writable stream for correct flow and backpressure handling.
Step 3: Evaluate other options
Directly write chunks from readable to writable without transformation skips transformation, C risks locking issues, and D transforms too late after writing.
Final Answer:
Pipe the readable through a TransformStream that uppercases chunks, then pipe to writable -> Option A
Quick Check:
Use TransformStream + pipeThrough + pipeTo = B [OK]
Hint: Use TransformStream between readable and writable for data changes [OK]
Common Mistakes:
Skipping TransformStream for data modification
Not handling stream locks properly
Transforming data after writing
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.