前端流式接收數(shù)據(jù)示例講解
前言
前端流式接收數(shù)據(jù)(Streaming Data Reception)是現(xiàn)代 Web 應(yīng)用中一個(gè)重要特性,尤其在處理實(shí)時(shí)通信、大文件傳輸、聊天、視頻播放、實(shí)時(shí)日志監(jiān)控等場(chǎng)景下。下面我們從概念到技術(shù)實(shí)現(xiàn),再到應(yīng)用示例,系統(tǒng)全面、細(xì)致地講解前端如何流式接收數(shù)據(jù)。
一、什么是流式接收數(shù)據(jù)?
傳統(tǒng)方式:前端發(fā)起請(qǐng)求,后端準(zhǔn)備好完整數(shù)據(jù)后一次性返回。
流式方式:后端逐步返回?cái)?shù)據(jù)片段(chunk),前端逐塊接收和處理,實(shí)現(xiàn)邊接收邊處理。
優(yōu)點(diǎn)
- 降低延遲,提升用戶體驗(yàn)
- 節(jié)省內(nèi)存
- 實(shí)現(xiàn)實(shí)時(shí)響應(yīng)(如 AI 回答、日志推送)
二、前端接收數(shù)據(jù)的主流流式方式
我們重點(diǎn)介紹以下幾種常見方式:
- Fetch + ReadableStream(原生流)
- EventSource(Server-Sent Events)
- WebSocket(雙向通信)
- ReadableStream + TransformStream(高級(jí)控制)
三、Fetch + ReadableStream(推薦)
1. 使用場(chǎng)景
用于接收后端以流式返回的數(shù)據(jù),例如:AI 輸出、長(zhǎng)日志、文件下載。
2. 示例代碼
<button id="start">開始接收流數(shù)據(jù)</button>
<pre id="output"></pre>
<script>
document.getElementById("start").addEventListener("click", async () => {
const output = document.getElementById("output");
output.textContent = "";
const response = await fetch("/stream-endpoint");
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
while (true) {
const { done, value } = await reader.read();
if (done) break;
output.textContent += decoder.decode(value, { stream: true });
}
});
</script>
3. 后端需支持 chunked 傳輸(如 Node.js、Flask、FastAPI)
四、EventSource(SSE:服務(wù)器推送)
1. 使用場(chǎng)景
適用于服務(wù)器主動(dòng)推送數(shù)據(jù),如股票價(jià)格、消息通知、日志流。
2. 示例代碼
<pre id="log"></pre>
<script>
const log = document.getElementById("log");
const evtSource = new EventSource("/sse");
evtSource.onmessage = (event) => {
log.textContent += `數(shù)據(jù):${event.data}\n`;
};
</script>
3. 服務(wù)端要求
- 設(shè)置響應(yīng)頭:
Content-Type: text/event-stream - 使用
data:格式發(fā)送數(shù)據(jù)
data: Hello data: World
五、WebSocket(全雙工通信)
1. 使用場(chǎng)景
適用于雙向通信場(chǎng)景:聊天室、在線游戲、協(xié)同編輯等。
2. 示例代碼
<input id="msg" placeholder="輸入消息" />
<button onclick="sendMessage()">發(fā)送</button>
<pre id="chat"></pre>
<script>
const ws = new WebSocket("ws://localhost:8080");
const chat = document.getElementById("chat");
ws.onmessage = (event) => {
chat.textContent += `服務(wù)器:${event.data}\n`;
};
function sendMessage() {
const msg = document.getElementById("msg").value;
ws.send(msg);
}
</script>
3. 服務(wù)端需實(shí)現(xiàn) WebSocket 協(xié)議(如:ws模塊、Socket.IO、FastAPI WebSocket)
六、ReadableStream + TransformStream(更高級(jí)的控制)
1. 使用場(chǎng)景
需要對(duì)流數(shù)據(jù)做實(shí)時(shí)處理、轉(zhuǎn)換,例如分割段落、轉(zhuǎn)義數(shù)據(jù)。
2. 示例代碼
const response = await fetch('/stream');
const textDecoderStream = new TextDecoderStream();
const transformStream = new TransformStream({
transform(chunk, controller) {
const timestamped = `[${new Date().toISOString()}] ${chunk}`;
controller.enqueue(timestamped);
}
});
response.body
.pipeThrough(textDecoderStream)
.pipeThrough(transformStream)
.pipeTo(new WritableStream({
write(chunk) {
document.body.innerText += chunk;
}
}));
七、如何選擇合適的方式?
| 需求 | 建議使用方式 |
|---|---|
| 單向、實(shí)時(shí)推送 | SSE(EventSource) |
| 雙向通信 | WebSocket |
| 邊接收邊展示長(zhǎng)文本/AI輸出 | Fetch + ReadableStream |
| 需要數(shù)據(jù)轉(zhuǎn)化、過濾 | TransformStream |
八、常見問題與調(diào)試技巧
1. 后端未設(shè)置Transfer-Encoding: chunked
確保響應(yīng)頭允許流式傳輸,否則瀏覽器會(huì)等全部?jī)?nèi)容加載完才顯示。
2. 瀏覽器兼容性問題
ReadableStream和TextDecoderStream在新瀏覽器中支持良好- SSE 不支持 IE
- WebSocket 跨域需特別配置
3. 網(wǎng)絡(luò)中斷/重連機(jī)制
- SSE 自帶斷線重連機(jī)制
- WebSocket 需手動(dòng)處理重連邏輯
九、延伸:結(jié)合前端框架(Vue/React)
以 Vue 為例:
<template>
<pre>{{ content }}</pre>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const content = ref('')
onMounted(async () => {
const response = await fetch('/stream');
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
content.value += decoder.decode(value);
}
});
</script>
十、總結(jié)
| 技術(shù) | 單向/雙向 | 控制能力 | 瀏覽器支持 | 用例 |
|---|---|---|---|---|
| Fetch Stream | 單向 | 強(qiáng) | 新版瀏覽器 | AI回答、實(shí)時(shí)日志等 |
| EventSource | 單向 | 中 | 較好(除IE) | 消息推送、狀態(tài)通知 |
| WebSocket | 雙向 | 強(qiáng) | 好 | 聊天、游戲、協(xié)同編輯 |
| TransformStream | 單向 | 很強(qiáng) | 較新瀏覽器 | 分段解析、關(guān)鍵詞處理等 |
到此這篇關(guān)于前端流式接收數(shù)據(jù)的文章就介紹到這了,更多相關(guān)前端流式接收數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解JavaScript兩個(gè)實(shí)用的圖片懶加載優(yōu)化方法
本文主要介紹了JavaScript兩個(gè)實(shí)用的圖片懶加載優(yōu)化方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
javascript實(shí)時(shí)顯示當(dāng)天日期的方法
這篇文章主要介紹了javascript實(shí)時(shí)顯示當(dāng)天日期的方法,可實(shí)時(shí)顯示當(dāng)前日期及星期的功能,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-05-05
微信小程序?qū)崿F(xiàn)YDUI的ScrollTab組件
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)YDUI的ScrollTab組件,滾動(dòng)選項(xiàng)卡效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
JavaScript給url網(wǎng)址進(jìn)行encode編碼的方法
這篇文章主要介紹了JavaScript給url網(wǎng)址進(jìn)行encode編碼的方法,實(shí)例分析了javascript中encodeURIComponent函數(shù)的使用技巧,需要的朋友可以參考下2015-03-03
JS去掉字符串前后空格、阻止表單提交的實(shí)現(xiàn)代碼
這篇文章主要介紹了JS去掉字符串前后空格、阻止表單提交的實(shí)現(xiàn)代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06

