用http方式实现websocket,如chatGPT时时打字效果,原生方式:fetch+sse+post
fetch实现stream、原生fetch+sse+post
fetch 本身不直接支持流式输出,但你可以使用 ReadableStream 和 TextDecoder 等 Web Streams API 来实现类似的效果。
后端:比如python, php, java 等等都行... 核心是前端,在下面会有完整展示
python
from fastapi import FastAPI, Response
from fastapi.responses import StreamingResponse
import json
import time
from fastapi.middleware.cors import CORSMiddleware #解决跨域
from fastapi import FastAPI, File, UploadFile,Form,Request
# from sse_starlette.sse import EventSourceResponse
app = FastAPI()
# 假设这是你想按事件流形式发送的JSON数据
data = {
"messages": [
{"text": "Hello, 1!", "timestamp": "2021-01-01T12:00:00"},
{"text": "Hello, 2!", "timestamp": "2021-01-02T12:00:01"},
{"text": "Hello, 3!", "timestamp": "2021-01-02T12:00:02"},
]
}
def generate_json_stream(data):
# 分割JSON数据,并逐个发送
for message in data["messages"]:
json_str = json.dumps(message)
yield json_str.encode("utf-8") #发送当前值给前端
time.sleep(1) # 模拟延时
# 配置 CORSMiddleware 跨域
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许访问的源
allow_credentials=True, # 支持 cookie
allow_methods=["*"], # 允许使用的请求方法
allow_headers=["*"] # 允许携带的 Headers
)
@app.post("/stream-json")
async def stream_json( request: Request,foo: str = Form(default='') ):
# 获取json
json_data = await request.json()
getHeader = request.headers
print('----1-----',json_data,getHeader)
# return EventSourceResponse(generate_json_stream(data), media_type="text/event-stream")
return StreamingResponse(generate_json_stream(data), media_type="text/event-stream")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=16887)
核心是前端:
javascript
<!DOCTYPE html>
<html>
<head>
<title>原生fetch+sse+post</title>
</head>
<body>
<div id="messages"></div>
<button id="sendDataButton" onClick="send()">发送</button>
<script>
function send() {
msg='123465';
// 发送 POST 请求
fetch('http://127.0.0.1:16887/stream-json', {//1、post提交
method:"POST",
body:JSON.stringify({ "content": msg}),
timeout: 0,
dataType:"text/event-stream",
headers:{
"Content-Type":"application/json"
},
}).then(response => {//2、post提交后返回的流
// 检查响应是否成功
if (!response.ok) {
throw new Error('网络响应异常');
}
// 返回一个可读流
return response.body;
}).then(body => {//3、对流进行时时打印
//disableLoading();//开始打印数据 ......
//获取时时数据
const reader = body.getReader();
// 时时打印 - 读取数据流
function read() {
return reader.read().then(({ done, value }) => {
// 检查是否读取完毕
if (done) {
console.log('已传输完毕');
return;
}
// 处理每个数据块
console.log('收到的数据:', value);
//把流处理成文本
value_to_txt = new TextDecoder().decode(value)
//json字符串 转 对象obj
var resultObj = JSON.parse(value_to_txt);
console.log(resultObj);
console.log('收到的数据 变成文本 :', value_to_txt );
// 递归调用自身 - 继续读取下一个数据块
read();
});
}
// 激活时时打印 - 开始读取数据流
read();
}).catch(error => {//捕捉异常
console.error('Fetch 异常:', error);
});
}
</script>
</body>
</html>