流式數據服務端怎么傳給前端,前端怎么接收?

01 引言

大模型時代,尤其會話模型為了提高用戶的使用體驗,它不會將所有的數據加載完成一次響應給客戶端,而是通過數據流,一點點的將數據慢慢呈現出來。

正是這種有趣的交互方式一次次將SSE(Server Sent Event)技術推到大眾視野。之前的文章已經介紹過SSE推送技術以及SSE替代WebSocket實現直播間實時評論功能的文章,這里就不在贅述。

恰巧,有位粉絲朋友咨詢怎么講流式數據傳給前端,前端怎么接收?小編為此做了相關的測試,整理在這里,分享給大家。

02 思維定式

我們經常編寫的是一次請求,一次響應這樣標準的http請求。如:

@RestController
public class FooController {@GetMapping("/foo")public String foo() {return "success";}
}

而流式數據該怎么處理呢?一次請求,有源源不斷的數據加載進來。如果按照思維定式處理,只能能到所有的數據全部加載完成,再響應給前端。這樣帶來的結果有:

  • 響應時間過長,體驗感很差
  • 響應超時,前端無法獲取到數據

流式數據返回在響應式編程里面非常普遍,如reactor.core.publisher.Fluxio.reactivex.Flowable等。我們姑且以FluxFlowable作為案例測試。

03 流式響應

3.1 Flux<T>

Fluxspring-boot-starter-webflux管理下的reactor-core.jar包。具體的Maven:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

案例

@GetMapping("/stream")
public Flux<String> streamData() {return Flux.interval(Duration.ofSeconds(1)).map(sequence -> {// 為了方便:拼接隨機數方便觀察String a = "flux_data: " + sequence + ":" +new Random().nextFloat();System.out.println(a);return a;});
}

瀏覽器直接訪問

我們可以看到正常的Http請求,只有等到所有的流數據處理完成之后才會一起展示出來。

3.2 Flowable<T>

Flowable是位于rxjava.jar包下。具體的Maven

<dependency><groupId>io.reactivex.rxjava2</groupId><artifactId>rxjava</artifactId><version>2.2.21</version>
</dependency>

案例

@GetMapping("/flowable")
public Flowable<String> flowable() {// 每隔一秒發送一條數據return Flowable.interval(1, TimeUnit.SECONDS).map(item -> {// 為了方便觀察,增加隨機數String data ="flowable_test:"+ item + "_" + new Random().nextFloat();System.out.println(data);return data;});
}

瀏覽器直接訪問

斷開服務器

3.3 前端接收

上面的案例均使用了瀏覽器直接訪問,類似使用了ajaxfetch等請求。我們以fetch為例:

$("button[name='send']").click(function (){fetch("/stream").then(resp => resp.text()).then(data => console.info(data));
});

結果

第一張圖中并沒有打印數據,而是等全部流數據完成之后才會打印展示。前端處理的話,同樣等到數據處理完成才能渲染。

這種常規的請求已然不能滿足我們的業務場景了。只能請出我們的大殺器SSE了。

04 前端處理流式請求

關于SSE這里不多介紹,詳細可以看詳細文檔說明:https://javascript.info/server-sent-events

4.1 前端直接處理流式數據

服務端只要返回流式數據即可,如Flux<T>Flowable<T>等。為了方便演示,我們通過按鈕出發接收流式數據。服務端和上面的案例相同。

JS代碼

$("button[name='send']").click(function (){let eventSource = new EventSource("/stream");eventSource.onmessage = function (event) {console.log("數據打印:" + event.data);}
});

結果

我們可以看到數據是一條一條返回給前端的。

4.2 服務端推數據給前端

不使用響應式編程的情況下,如何將數據逐步推給前端呢?那就通過org.springframework.web.servlet.mvc.method.annotation.SseEmitter,手動推送給前端。

前端的JS代碼只需要訂閱指定的路徑,然后監聽消息即可。寫法同4.1

JS代碼

$("button[name='send']").click(function (){let eventSource = new EventSource("/subscription");eventSource.onmessage = function (event) {console.log("數據打印:" + event.data);}
});

服務端

SseEmitter sseEmitter;@GetMapping("/subscription")
public SseEmitter sseEmitter() {sseEmitter = new SseEmitter();return sseEmitter;
}@PostConstruct
public void timer() {new Timer().schedule(new TimerTask() {@Overridepublic void run() {if (sseEmitter != null) {try {sseEmitter.send("sseEmitter_" + new Random().nextFloat());} catch (IOException e) {throw new RuntimeException(e);}}}}, 1000, 1000);
}

通過/subscription訂閱,并生成對應的客戶端。服務端推送消息,都是通過這個客戶端推送的。timer()定時器模擬數據自動推送。

我們直接看前端的效果:

當然我們對接業務中需要考慮連接超時的問題,以及頁面多開客戶端區分的問題。這部分內容可以參考之前的文檔:SSE 推送技術

05 小結

流式數據對于大數據量的處理展示比較常見,包括Mybaits也支持流式查詢,防止頻繁的數據庫連接池的打開和關閉。流式處理一般都是長連接,長連接勢必帶來資源的占用。用不好,可能造成連接池沾滿、內存溢出等意想不到的問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919076.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919076.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919076.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ML307C 4G通信板:工業級DTU固件,多協議支持,智能配置管理

產品概述 ML307C 4G通信板是一款基于中移物聯網ML307C模組的工業級DTU&#xff08;數據傳輸單元&#xff09;產品&#xff0c;專為工業物聯網應用設計。我們的固件支持多種工業協議&#xff0c;具備遠程配置、FOTA升級、數據加密等企業級功能&#xff0c;為您的工業設備提供穩定…

Sublime配置verilog開發環境-具備語法高亮、代碼補全、自定義代碼段及語法檢查等功能,提升FPGA開發效率!

對于在學習FPGA開發之前使用過其他集成開發工具如VS、pycharm、keil或編輯工具如Sublime、VScode、Notepad的朋友&#xff0c;在使用Vivado時可能會像博主一樣感覺自帶編輯器用起來不太舒服&#xff0c;比如不支持語法高亮顯示&#xff0c;不支持代碼自動補全等功能。因次&…

18_基于深度學習的煙霧檢測識別系統(yolo11、yolov8、yolov5+UI界面+Python項目源碼+模型+標注好的數據集)

目錄 項目介紹&#x1f3af; 功能展示&#x1f31f; 一、環境安裝&#x1f386; 環境配置說明&#x1f4d8; 安裝指南說明&#x1f3a5; 環境安裝教學視頻 &#x1f31f; 二、數據集介紹&#x1f31f; 三、系統環境&#xff08;框架/依賴庫&#xff09;說明&#x1f9f1; 系統環…

【計算機網絡架構】混合型架構簡介

引言在當今數字化浪潮席卷全球的背景下&#xff0c;網絡技術正以前所未有的速度迅猛發展&#xff0c;各種網絡架構如雨后春筍般涌現。從早期簡單的總線型、星型架構&#xff0c;到后來的環型、樹型架構&#xff0c;再到如今復雜的網狀型、云計算架構等&#xff0c;每一種架構都…

Hexo 雙分支部署指南:從原理到 Netlify 實戰

Hexo 雙分支部署指南&#xff1a;從原理到 Netlify 實戰 在 Hexo 博客部署中&#xff0c;很多人會困惑于hexo d自動部署與 GitHub 手動提交的區別&#xff0c;以及如何通過雙分支結構優雅地部署到 Netlify。本文將清晰拆解兩種部署方式的核心差異&#xff0c;并手把手教你用雙分…

【數據結構】深入理解單鏈表與通訊錄項目實現

文章目錄一、單鏈表的概念及結構1.1 什么是單鏈表&#xff1f;1.2 節點的組成1.3 單鏈表的特點二、單鏈表的實現2.1 類型定義2.2 基礎工具函數1. 鏈表打印函數2. 節點創建函數2.3 單鏈表的核心操作&#xff08;1&#xff09;插入操作1. 尾插&#xff08;SLTPushBack&#xff09…

《Python學習之字典(一):基礎操作與核心用法》

堅持用 清晰易懂的圖解 代碼語言&#xff0c;讓每個知識點變得簡單&#xff01; &#x1f680;呆頭個人主頁詳情 &#x1f331; 呆頭個人Gitee代碼倉庫 &#x1f4cc; 呆頭詳細專欄系列 座右銘&#xff1a; “不患無位&#xff0c;患所以立。” Python學習之字典&#xff08;…

[安洵杯 2019]Attack

BUUCTF在線評測BUUCTF 是一個 CTF 競賽和訓練平臺&#xff0c;為各位 CTF 選手提供真實賽題在線復現等服務。https://buuoj.cn/challenges#[%E5%AE%89%E6%B4%B5%E6%9D%AF%202019]Attack流量分析題&#xff0c;瀏覽的時候發現攻擊者上傳信息頁面&#xff0c; 直接搜索 flag 就…

復合機器人食品分揀生產線:一體化控制系統引領高效柔性新食代

在食品工業高速發展的今天&#xff0c;面對種類繁多、形態各異的原料分揀需求&#xff0c;以及日益嚴格的衛生安全與效率要求&#xff0c;傳統的固定式分揀設備已難以勝任。復合機器人食品分揀生產線憑借其融合移動&#xff08;AMR&#xff09;與操作&#xff08;機械臂&#x…

二十七、動態SQL

動態SQL介紹動態SQL&#xff1a;if與where標簽動態案例-動態更新EmpMapper&#xff08;接口&#xff09;中對應代碼塊 //動態更新員工public void update2(Emp emp);EmpMapper.xml中對應代碼塊 <!-- 動態更新員工--><update id"update2">update emp<s…

AI可行性分析:數據×算法×反饋=成功

3.1 從場景到AI可行性分析:需求拆解為“數據+算法+反饋” 核心公式: AI可行性 = 數據可獲得性 算法適配性 反饋閉環性 (任一要素為0則需求不可行) 一、傳統需求 vs AI需求本質差異 需求文檔對比(電商案例) 維度 傳統需求文檔(購物車功能) AI需求文檔(商品推薦系…

【圖論】分層圖 / 拆點

大多數都是同一個套路&#xff0c;將圖拆開成幾個圖&#xff0c;每一層都對應著一個不同的狀態&#xff0c;比如把到點 i 的狀態拆成經過了 j 次操作所得的 xx 結果&#xff0c;一般數據不會很大 目前遇到的可分為 3 類&#xff1a; ①.給你最多 k 次操作&#xff0c;求 xx 結…

VS Code配置MinGW64編譯MATIO庫

VS Code 使用 MinGW64 編譯 C 代碼并配置 MATIO 庫的完整步驟 1. 安裝 MSYS2 下載 MSYS2 訪問 MSYS2 官網下載安裝包&#xff08;選擇 x86_64 版本&#xff09;默認安裝路徑&#xff1a;C:\msys64 更新 MSYS2 包數據庫 打開 MSYS2 MinGW 64-bit&#xff08;注意不是 MSYS&…

【前端Vue】使用ElementUI實現表單中可選擇可編輯的下拉框

由于項目在vue的開發框架下&#xff0c;因此使用ElementUI組件庫進行實現。我希望可選擇可編輯的下拉框右側有跟下拉框一樣的箭頭&#xff0c;并且在未輸入任何內容時&#xff0c;點擊該框體會出現選擇列表進行填充數據的選擇&#xff0c;點擊選中數據后列表消失&#xff0c;數…

每日五個pyecharts可視化圖表-line:從入門到精通 (4)

歡迎來到pyecharts折線圖系列的第四篇文章&#xff01;在前三篇中&#xff0c;我們已經掌握了多種折線圖類型&#xff0c;包括基本折線圖、平滑折線圖、雨量流量關系圖、多X軸折線圖、堆疊區域圖和階梯圖等。在本文中&#xff0c;我們將繼續探索五種更高級的折線圖類型&#xf…

MySQL中的字符串函數

目錄 一、字符串【分割】函數&#xff1a;SUBSTRING_INDEX() SUBSTRING_INDEX函數 練習題 統計每種性別的人數 提取博客URL中的用戶名 截取出年齡 SQL83 商品id數據清洗統計 SQL250 查找字符串中逗號出現的次數 二、字符串【截取】函數&#xff1a;SUBSTRING() 基本語…

CodeBuddy IDE深度體驗:AI驅動的全棧開發新時代

在人工智能技術迅猛發展的今天&#xff0c;開發者工具正在經歷一場深刻的變革。騰訊推出的CodeBuddy IDE作為全球首個“產設研一體”的AI全棧高級工程師工具&#xff0c;重新定義了開發者的日常工作流程。 從需求分析到設計、編碼、部署&#xff0c;CodeBuddy通過AI能力將傳統…

實現Android圖片手勢縮放功能的完整自定義View方案,結合了多種手勢交互功能

主要功能特點&#xff1a;支持雙指手勢縮放圖片&#xff0c;通過ScaleGestureDetector實現平滑的縮放效果25雙擊圖片可切換初始大小和中等放大比例16使用Matrix進行圖像變換&#xff0c;保持縮放中心點為手勢焦點位置57自動縮放動畫通過Runnable實現漸進式變化1限制最小和最大縮…

uni-app實戰教程 從0到1開發 畫圖軟件 (橡皮擦)

一、本期內容簡述1. 開發內容上一期&#xff0c;我們一起學習了如何進行繪畫&#xff0c;本期我們將學習如何擦除我們所繪畫的內容&#xff0c;也就是“橡皮擦”功能。首先&#xff0c;我們應該明確需求&#xff0c;橡皮擦可以擦除掉我們繪畫的內容。2. 開發需求所以開發需求&a…

《A Practical Guide to Building Agents》文檔學習

《A Practical Guide to Building Agents》文檔總結 該文檔是一份面向產品和工程團隊的實用指南&#xff0c;旨在幫助團隊探索并構建首個基于大語言模型&#xff08;LLM&#xff09;的智能體&#xff08;Agent&#xff09;&#xff0c;提煉了大量客戶部署經驗&#xff0c;提供了…