流式接口解析及数据展示

前言

此处为一个流式接口的对话,前端需要以流式的方式进行输出。前端框架使用Vue3

  • HTML

说明:此处将展示对话内容的多于元素已删除,只保留了消息体的HTML。

<div v-for="item in data" class="chat-item">
    <div :class="'message ' + item.type">
        <div class="response-info">
            <span class="message-text">{{ item.content }}</span>
        </div>
    </div>
</div>
  • JavaScript

定义streamChatData为获取流式数据的方法。在data不断变化的过程中,HTML中的消息就会以流式的方式打印出来。

const streamChatData = async (params) => {
	// data为存储对话的数组
    data.value.push({
        type: 'response',
        content: '正在获取答案中...'
    })
    
    // 流式接口地址
    const url = `${base_chat}/xxxx/chat`
    
    try {
        const access_token = Cookies.get('access_token')
        
        // 发送请求
        const response = await fetch(url, {
            method: 'post',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${access_token}`
            },
            mode: 'cors',
            body: JSON.stringify(params)
        })
        if(!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`)
        }
        // console.log(`获取的数据大小${response.headers.get('content-length')/1000/1000}M`)
        data.value[data.value.length - 1].content = ''
        const reader = response.body?.getReader()
        const dispatchRaw = async (raw: string) => {
            raw = raw.trim();
            const matches = raw
                .split("data:")
                .map((item: string) => item.trim())
                .filter((item: string) => item)
            for (let va of matches) {
                va = !!va && JSON.parse(va) || {}
                await onMessagData(va)
            }
        }
        while(true) {
            const { value, done } = await reader?.read()
            if(done) {
                console.log('stream done')
                isResponsed.value = true
                break
            }
            const utf8Decoder = new TextDecoder("utf-8");
            let raw: any = value ? utf8Decoder.decode(value, { stream: true }) : ''
            console.log('stream raw:', raw)
            dispatchRaw(raw)
            // isResponsed.value = true
        }
    } catch(err) {
        console.log(err)
    }
}

const onMessagData = (va) => {
    data.value[data.value.length - 1].content += va?.message || ''
}

扩展

实现将一个字符串以打字机的效果输出,每次只打印一个字。

  • HTML
<span>{{ text }}</span>
  • JavaScript
// 定义一个完整的字符串
let fullText = ref('Hello Typewriter Effect!')

// HTML中展示的字符串
let text = ref()

// 定义打字机打印的方法
const typeWriter = (index) => {
    if(index < fullText.value.length) {
        text.value = fullText.value.slice(0, index)
    }
    setTimeout(() => {
        typeWriter(index + 1)
    }, 100);
}
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值