fetch流式接口
时间: 2025-03-20 17:16:47 浏览: 62
### 使用 Fetch API 实现流式接口并处理 Stream 数据
Fetch API 提供了一种现代的方式来发起网络请求,并支持多种高级功能,其中包括对流式数据的支持。以下是关于如何使用 `fetch` 来实现流式接口以及处理流式数据的具体方法。
#### 1. 流式接口的概念
流式接口允许客户端逐步接收服务器返回的数据,而不是等待整个响应完成后再一次性获取全部内容。这种技术特别适用于实时更新场景,比如聊天应用中的消息推送或者 AI 对话系统的逐字显示效果[^3]。
#### 2. 使用 Fetch 接收流式数据的示例代码
下面是一个完整的 JavaScript 示例,展示如何利用 `fetch` 和 `ReadableStream` 来读取来自服务器端的流式数据:
```javascript
// 发起 GET 请求到流式接口
const response = await fetch('http://localhost:8080/api/stream', {
method: 'GET',
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// 获取 ReadableStream 并将其转换为文本形式
const reader = response.body.getReader();
let resultText = '';
function readStream() {
reader.read().then(({ done, value }) => {
if (done) {
console.log('Stream complete:', resultText);
return;
}
const chunk = new TextDecoder("utf-8").decode(value); // 将 Uint8Array 转换为字符串
resultText += chunk;
// 动态打印接收到的内容(可替换为其他逻辑)
process.stdout.write(chunk);
// 继续读取下一个片段
readStream();
}).catch((error) => {
console.error('Error while reading stream:', error);
});
}
readStream(); // 开始读取流
```
上述代码展示了如何通过 `getReader()` 方法从 `response.body` 中创建一个读取器实例,并循环调用其 `read()` 函数来逐一解析每个数据块[^1]。
#### 3. 向服务端发送二进制数据作为流
除了接收流之外,还可以借助 `fetch` 的能力向远程服务器提交大文件或其他类型的二进制资源。例如,在上传图片时可以采用如下方式:
```javascript
async function uploadImage(canvasElement) {
try {
// 创建一个新的 Promise 解析 Canvas 图像为 Blob 格式的图像数据
const blob = await new Promise(resolve => canvasElement.toBlob(resolve, 'image/png'));
// 配置 POST 请求参数并将 Blob 放入 body 字段中
const response = await fetch('/upload-image-endpoint', {
method: 'POST',
headers: { 'Content-Type': undefined },
body: blob,
});
if (!response.ok) {
throw new Error(`Upload failed with status code ${response.status}`);
}
console.log('Image uploaded successfully.');
} catch (err) {
console.error(err.message || err.toString());
}
}
```
此部分说明了如何将画布上的图形导出成 PNG 文件并通过 HTTP 协议传递给目标地址[^2]。
#### 4. 结合 UniApp 进行更复杂的交互操作
对于跨平台框架如 UniApp,则可以通过内置工具链进一步简化开发流程。以下是从官方文档摘录的一个例子,它演示了一个简单的对话框组件如何结合流控机制渲染动态加载的文字串:
```html
<template>
<div v-if="isStreaming">
{{ dialogue }}
</div>
<button @click="startStreaming">Start Streaming</button>
</template>
<script>
export default {
data() {
return {
isStreaming: false,
dialogue: '',
abortController: null,
};
},
methods: {
async startStreaming() {
this.isStreaming = true;
this.abortController = new AbortController();
const signal = this.abortController.signal;
try {
const res = await fetch('/stream-dialogue', { signal });
if (!res.ok) throw new Error(res.statusText);
const reader = res.body.getReader();
let decoder = new TextDecoder();
while(true){
const {value, done} = await reader.read();
if(done){
break;
}
this.dialogue += decoder.decode(value,{stream:true});
}
} finally{
this.isStreaming=false;
}
},
stopStreaming(){
if(this.abortController && !this.abortController.signal.aborted){
this.abortController.abort();
}
}
}
};
</script>
```
这段脚本定义了一个 Vue.js 组件,其中包含了两个主要函数——一个是用来开启新的会话序列;另一个则是中断当前正在进行的任务。
---
###
阅读全文
相关推荐


















