Stream Output Demo in Javascript

Introduction

I’ve recorded an MP4 demo to showcase the results. In the video, you’ll see the Markdown content being displayed
character by character, with dynamic rendering and automatic scrolling.

Demo MP4

In this article, I’ll walk you through a simple yet powerful demo of implementing stream output in JavaScript. This
demo
mimics the behavior of ChatGPT-like applications, where responses are displayed in a streaming fashion, and the
content
is dynamically rendered as Markdown. The best part? It’s incredibly simple to implement, and I’ll provide the full
source code and an MP4 demo to showcase the results.

What is Stream Output?

Stream output is a technique where data is displayed incrementally, rather than all at once. This is particularly useful
for applications like chatbots, where users expect to see responses appear in real-time, character by character or word
by word. In this demo, we’ll simulate this behavior using JavaScript and a local mock backend.

Key Features of the Demo

  1. Streaming Output: Responses are displayed incrementally, simulating a real-time experience.
  2. Markdown Rendering: The content is formatted as Markdown and dynamically rendered using the marked.js library.
  3. Local Mock Backend: No need for a real server—we’ll simulate the streamed data locally.
  4. Simple Code: The implementation is straightforward and easy to understand.

Full Source Code

You can find the full source code for this demo below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
</head>
<body>
<div
id="chat-output"
style="border: 1px solid #ccc; padding: 10px; height: 300px; overflow-y: auto;"
></div>
<label for="chat-input"></label><textarea id="chat-input"></textarea>
<button onclick="simulateStreamResponse()">Send</button>
<script></script>
</body>
<script>
const mockResponse = `
# Hello Edward,

This is a **stream output** example.

- Support Markdown format.
- Support dynamic scrolling to latest content.
- Soft scroll to latest content.

**Code Example**
\`\`\`javascript
const showMem = function () {
const mem = process.memoryUsage()
const format = function (bytes) {
return (bytes / 1024 / 1024).toFixed(2) + 'MB'
}

console.log(
\`total:\${format(mem.heapTotal)}, used: \${format(
mem.heapUsed,
)}, rss: \${format(mem.rss)}\`,
)
console.log('-----------------------')
}

const useMem = function () {
const size = 20 * 1024 * 1024 // 20MB
const arr = new Buffer(size).fill(0)

return arr
}

const total = []

for (let i = 0; i < 15; i++) {
showMem()
total.push(useMem())
}

showMem()
\`\`\`
`

function simulateStreamResponse() {
const chatOutput = document.getElementById("chat-output")
let index = 0
let buffer = ""

const interval = setInterval(() => {
if (index >= mockResponse.length) {
clearInterval(interval)
return
}

buffer += mockResponse[index]
index++

chatOutput.innerHTML = marked.parse(buffer)

chatOutput.scrollTop = chatOutput.scrollHeight
}, 50)
}
</script>
</html>