普通数据

前端

发送:axios

接收:then里面些接收值

后端

发送:json

接收:request.json

流式数据

前端接收

 先将字节码数据转成json 就是正常的

根据传过来的对象,看是否发送完毕

后端发送

stream

 

 example

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img alt="Vite logo" class="logo" src="/vite.svg"/>
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img alt="Vue logo" class="logo vue" src="./assets/vue.svg"/>
    </a>
  </div>
  <div class="container">
    <div class="module">
      <h1>接收普通数据</h1>
      <input v-model="data">
      <button @click="send">发送数据</button>
      <div v-if="response">
        <h2>从后端接收到的数据:</h2>
        <p>{{ response }}</p>
      </div>
    </div>
    <div class="module">
      <h1>接收流式数据</h1>
      <!--      <input v-model="streamdata">-->
      <button @click="StreamSend">接收</button>
      <div>
          <a v-for="(response, index) in streamResponse" :key="index">
            {{ response }} <!-- 假设response是直接可显示的字符串或已经是处理过的格式 -->
          </a>
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref} from 'vue'
import axios from 'axios'
// 使用ref来响应式地存储流数据
const streamResponse = ref([]) // 将单个响应改为数组,以存储流中的每个数据点

const response = ref(null)
const data = ref('')

function send() {
  axios.post('http://127.0.0.1:8090/chat', {
    id: 1,
    name: data.value
  }).then(
      res => {
        console.log(res.data)
        response.value = res.data['message']
      }
  ).catch(
      error => {
        console.error('请求错误', error)
      }
  )

}

function StreamSend() {
  const url = 'http://127.0.0.1:8090/streamchat'
  const params = {message:"已发送"}

  // 使用fetch API发起POST请求
  fetch(url, {
    method: 'POST', // 请求方法
    headers: {
      'Content-Type': 'application/json', // 请求头,指定内容类型为JSON
    },
    body: JSON.stringify(params), // 将请求参数对象转换为JSON字符串
  }).then(response => {
        const reader = response.body.getReader() // 获取响应体的读取器
        const decoder = new TextDecoder('utf-8') //将字节流中的UTF-8编码字节转换成JavaScript字符串的方法//网络传输的数据通常是以字节流形式存在的,这些字节代表了文本的UTF-8编码形式。为了在JavaScript中处理这些文本数据(比如显示消息、解析JSON等),需要将其从字节转换为字符串
        let sy = "" //异常处理的,
        // 逐块处理响应流,将字节码数据解码出来。 result是reader.read
        function ReadableStream(result) {
          let line = decoder.decode(result.value, {stream: !result.done})  //result.value 是字节码 解码当前块,并根据结果是否完整来决定是否停止流式传输/line=data: 2
          // 将新解码的数据与之前可能残留的数据拼接
          line = sy + line
          console.log('line',line)
          sy = "" // 清空拼接缓存
          // 特殊处理:如果数据包含"ping",则过滤掉这部分 。。为什么会包含ping
          if (line.includes("ping")) {
            const errs = line.split('\n')
            let raw = []
            errs.forEach(e => {
              if (!e.includes("ping") && e.startsWith("data")) {
                raw.push(e)
              }
            })
            // 重新组合过滤后的数据
            line = raw.join("\n")
          }
          // 以'data:'作为分隔符分割数据,每个部分代表一个独立的消息 ['', ' 9\n\n']
          const lines = line.split('data:')
          console.log('aaaa',lines)
          lines.forEach(e => {  //拿到解码后的值
            console.log('e',e)
            if (!e) return // 如果分割后的某部分为空,则跳过
            let value;
            try {
              value = JSON.parse(e)// 尝试解析为JSON对象
              streamResponse.value.push(value)
              console.log('解码后',value)
            } catch (err) {
              // 如果JSON.parse(e)抛出错误,这通常意味着e不是一个有效的JSON字符串。这种情况下,假设错误是因为数据被不幸地分割到了两个块中,所以把当前字符串e赋值给sy
              sy = e
              return
            }

            console.log('sss',value)// 此处可以添加处理逻辑,例如合并相同uuid的消息等
          })
          // 如果读取操作没有完成(result.done为false),ReadableStream函数将再次调用reader.read().then(ReadableStream),继续读取下一个数据块。
          if (!result.done) {
            return reader.read().then(ReadableStream)
          }
        }


        return reader.read().then(ReadableStream)
      }
  )
}

</script>

<style>
.container {
  display: flex; /* 使用 Flexbox 布局 */
}

.module {
  flex: 1; /* 设置模块的弹性,使其平均占据可用空间 */
  margin-right: 130px; /* 可选:增加模块之间的间距 */
  margin-left: 130px; /* 可选:增加模块之间的间距 */
}

</style>

  

 

from flask import Flask, request, jsonify, Response
from flask_cors import CORS
import requests
import json
import pandas as pd
import re
import time
app = Flask(__name__)
CORS(app)


@app.route('/chat', methods=['POST'])
def submit_data():
    # 从前端请求中获取数据
    data_from_frontend = request.json
    print(data_from_frontend['name'])

    # 假设进行了一些处理后,要返回给前端的数据
    processed_data = {'status': 'success', 'message': '前端发送的 {} 我已成功接收'.format(data_from_frontend['name'])}

    # 将处理后的数据返回给前端
    return jsonify(processed_data)

def generate_stream():
    # 这里是你的数据生成逻辑
    # 作为示例,我们每秒发送一个数字
    for number in range(10):  # 假设我们发送10次数据
        yield f"data: {number}\n\n"  # 注意格式:data: <数据>\n\n
        time.sleep(1)  # 模拟数据生成延迟

@app.route('/streamchat', methods=['POST'])
def stream_chat():
    print(request.json)
    data_stream = request.json['message']
    if data_stream =='已发送':
        # 创建一个生成器作为响应体,content_type 设置为 text/event-stream
        return Response(generate_stream(), content_type='text/event-stream')


if __name__ == '__main__':
    app.run(port=8090)

  

posted on 2024-03-12 18:02  黑逍逍  阅读(4)  评论(0编辑  收藏  举报