java + vue 实现 AI流式输出(打字机效果)
一、前言
我们在使用ai问答的时候, ai回答都是一个字一个字那种流式输出, 那么这种效果如何用技术实现呢? 其实方式很多, 我写了两个demo, 一种是前端定时追加的假流式, 一种是真实的后端返回流式。
二、前端实现假流式
let content = "润色版本(分场景提供)\n" +"\n" +"1. 诗意风格\n" +"十月的天空像被水洗过一般澄澈,暖阳为云朵镶上金边,连风都裹着桂花的甜香,这样的好天气,仿佛连时光都变得柔软起来。\n" +"\n" +"2. 简洁风格\n" +"今天是个晴空万里的好日子,阳光和煦,微风不燥,适合出门走走。\n" +"\n" +"3. 细节描写\n" +"午后三点的阳光斜斜地铺在窗台上,天空蓝得没有一丝杂质,偶尔飘过的云朵像棉花糖般轻盈。这样的天气,连呼吸都带着秋日的清爽。\n" +"\n" +"如需调整风格或补充细节,可随时告知具体方向(如更温暖/更简洁/增加比喻等)。"let len = content.length;let i = 0;aiText.value = "";setInterval(() => {if (i < len) {aiText.value += content[i];i++;}}, 100);
三、真正的流式输出
前端可以选择:fetch、Server-Sent Events (SSE)、WebSocket
后端可以选择:HttpServletResponse、SseEmitter返回、通过webflux
我这里前端用的浏览器原生的fetch, 后端用java的HttpServletResponse
1、后端
/*** aaa*/@PostMapping("/aaa")public void aaa(@RequestBody UserBean userBean, HttpServletResponse servletResponse) {try(ServletOutputStream outputStream = servletResponse.getOutputStream()) {int i = 0;while (i < 60) {String item = "流" + i;outputStream.write(item.getBytes());outputStream.flush();i++;Thread.sleep(1000);}}catch (Exception e) {logger.error("异常", e);}}
2、前端
function aiButtonEnd() {aiText.value = "";// 发送流式请求fetch("/zenglingyao/aaa", {method: "POST",headers: {'Authorization': `Bearer ${getToken()}`,'Content-Type' : 'application/json;charset=utf-8'}, body: JSON.stringify({})}).then(async (response) => {const reader = response.body.getReader();while (true) {const { done, value } = await reader.read();if (done) break;let contentItem = new TextDecoder().decode(value);aiText.value += contentItem;}}).catch((error) => {console.error("Fetch error:", error);});
}