用http方式实现websocket,如chatGPT时时打字效果,原生方式:fetch+sse+post

用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>
相关推荐
喵叔哟12 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生18 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
sinat_3842410918 分钟前
在有网络连接的机器上打包 electron 及其依赖项,在没有网络连接的机器上安装这些离线包
javascript·arcgis·electron
hopetomorrow32 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
小牛itbull41 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
nuclear20111 小时前
使用Python 在Excel中创建和取消数据分组 - 详解
python·excel数据分组·创建excel分组·excel分类汇总·excel嵌套分组·excel大纲级别·取消excel分组
533_1 小时前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js
闲暇部落1 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
GIS瞧葩菜1 小时前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript