從 Spring 流式傳輸 JSON Patch 到 React UI

工程 | Brian Cavalier | 2014 年 10 月 8 日 | ...

我們正在探索各種方法來幫助開發者建立富裕、現代化的前端,這些前端可以輕鬆地與 Spring 後端整合。如果您參加了今年的 SpringOne 大會,您已經看到了一些我們一直在努力實現的東西

  1. Spring Data REST 中的超媒體支援,由 Greg Turnquist、Oliver Gierke 和 Roy Clarkson 演示
  2. RaveJS:JavaScript 應用的 Spring Boot 概念,作者:John Hann
  3. 差分同步和 JSON Patch,作者:Craig Walls 和我

簡而言之,我們希望讓 Spring 後端和客戶端之間的高效通訊變得容易,並輕鬆整合最好和最流行的客戶端技術。

React + 流式更新

JSON Patch 是一種用於傳送結構化資料增量更改的格式。我認為嘗試透過 STOMP 將 JSON Patch 格式的更新流式傳輸到 Web UI 中會很有趣。

Craig Walls 已經使用新的 Spring Sync 專案構建了一個簡單的足球比分概念驗證,該專案透過 STOMP 使用 JSON Patch 將比分更新推送到瀏覽器。我利用了他的概念驗證,引入了 RaveJS,添加了客戶端響應式流,並將更新整合到一個 React UI 元件中。

您可以在我的 github 倉庫的 rave-most-react 分支中找到完整的程式碼。伺服器與 Craig 的原始版本保持不變。Web 客戶端是主要操作發生的地方。在我們深入瞭解具體細節之前,請先檢視 main.js 以瞭解整個應用的大致情況

開始

我使用 RaveJS 和 npm 管理我的客戶端依賴項,所以我的啟動很簡單

> cd src/main/resources/public

> npm init

<answer a few questions>

> npm install --save rave most jiff react rave-load-jsx rave-node-process stompjs

然後我只需要在現有的 HTML 中新增一個指令碼標籤,就可以開始編寫程式碼了!

<script src="node_modules/rave/rave.js"></script>

引入 most.js

感謝 Craig,我已有一個(JSON Patch 格式的)更新流透過 STOMP 流向客戶端。我認為處理補丁流的最佳方式是(驚喜!)*實際使用流*。

Most.js 是 cujoJS 的新 JavaScript 響應式流包。它提供了一組小而強大的 API,用於建立、轉換和使用事件流。我用它來包裝 stompjs API。

事實證明,有兩個 STOMP 訂閱:一個攜帶所有比分資料的初始完整副本,另一個攜帶所有後續更改。我能夠透過使用 jiff.js 應用到達的 JSON Patch,將這兩個訂閱包裝成一個表示“最新比分集”的單一響應式流。

這段程式碼從 STOMP 對初始資料的訂閱建立了一個流,獲取第一個事件(所有比分的完整快照),並將其與另一個僅包含 JSON Patch 更新的流結合,從而產生一個隨時間變化的比分檢視。

function getScoresStream(initDestination, updateDestination, client) {
	// Create a stream containing one full copy of the data, and
	// flatMap that to a stream containing the time-varying
	// current set of scores, by accumulating each patch
	// and emitting the updated scores data.
	return getInitialDataStream(initDestination, client)
		.flatMap(function(data) {
			return getUpdatesStream(updateDestination, client, data);
		});
}

function getInitialDataStream (initDestination, client) {
	// Await a copy of the data from the STOMP subscription
	// that is sending the full scores data, then unsubscribe.
	return streamFromStompJson(initDestination, client)
		.take(1);
}

function getUpdatesStream (updateDestination, client, data) {
	// Incrementally accumulate patches from the STOMP subscription
	// that is carrying JSON Patches onto the scores data to produce
	// an updated view of the scores.
	return streamFromStompJson(updateDestination, client)
		.startWith([])
		.scan(updateWithJsonPatch, data);
}

Most.js 在流結束時還會自動清理底層資源。在接收到完整比分資料的初始副本後,可以輕鬆安排取消第一個訂閱,只留下一個訂閱:變更訂閱。

使用 React 構建 UI

現在我已經有了代表最新比分的單一 most.js 流,我建立了一個 React 元件來顯示它們。我安裝了(見上文)rave-load-jsx 擴充套件,這是一個由社群成員建立的 RaveJS 擴充套件,它可以在 RaveJS 中直接載入 JSX 元件。我只需要建立一個 Scoreboard.jsx 檔案,然後開始編寫一個簡單的 React 記分板元件。

React 元件有一個內部的 state 物件,其中包含用於渲染元件的資料。我只需在建立元件時傳遞最新的比分流,然後讓元件觀察該流並更新其 state。相關的程式碼只有幾行

// this.props.scores is the scores stream provided when the
// Scoreboard component is created

this.props.scores.observe(function(scores) {
	self.setState({ scores: scores });
});

React 負責自動保持 DOM 與 state 同步。

從位元組到畫素

誠然,這是一個玩具應用。然而,它在一個非常小的空間內,用非常少的程式碼展示了許多強大的概念協同工作:小型的伺服器生成增量透過 STOMP + WebSocket 流動,到達客戶端的響應式流,並被 React 元件觀察。變化從 Spring 後端一直流向 UI——可以說是從位元組到畫素。

我希望這個小應用也能讓您一窺我們未來的方向。我們希望提供工具和客戶端包,幫助開發者構建富裕、現代化的客戶端應用,這些應用可以與主流的客戶端技術和 Spring 後端整合。

訂閱 Spring 時事通訊

透過 Spring 時事通訊保持聯絡

訂閱

先人一步

VMware 提供培訓和認證,助力您的進步。

瞭解更多

獲取支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

近期活動

檢視 Spring 社群的所有近期活動。

檢視全部