如何使用 webflux 端点从 React 生成 json 流
how consume webflux end point producing json streams from React
我想了解如何使用 WebFlux restcontroller 从 React 生成 json 流。我的第一个尝试迫使我解析为 json 的文本 instetad,但我觉得我在做一些奇怪的事情。我决定投入精力阅读周围的例子,我发现了一个例子 returning org.reactivestreams.Publisher 而不是 returning WebFlux。
我发现了一个有点老的话题可以帮助我 (Unable to Consume Webflux Streaming Response in React-Native client),但它没有一个答案。好吧,这促使我去某个地方读到 React 可能不符合 Reactive 但这是一个非常古老的 post.
从网上拿个例子,如果你看https://developer.okta.com/blog/2018/09/25/spring-webflux-websockets-react基本上你会发现:
WebFlux 产生 Json 但不流式传输:
RestController producing MediaType.APPLICATION_JSON_VALUE and returning org.reactivestreams.Publisher<the relevant pojo>
反应消耗 json:
async componentDidMount() {
const response = await fetch('relevant url');
const data = await response.json();
}
我尝试过类似的方法,但有两个显着差异:
我正在 returning MediaType.TEXT_EVENT_STREAM_VALUE 因为我相信我应该更喜欢 return 流,因为我正在使用无阻塞代码,而不是 returning org.reactivestreams.Publisher 我理解 return Webflux 更有意义,以便正确利用 Spring 5+.
我的 Webflux 休息控制器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.mybank.web.model.Loans;
import com.mybank.web.service.LoansService;
import reactor.core.publisher.Flux;
@RestController
public class LoansController {
@Autowired
private LoansService loansService;
@CrossOrigin
@RequestMapping(method = RequestMethod.GET, produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ResponseBody
public Flux<Loans> findAll() {
Flux<Loans> loans = loansService.findAll();
return loans;
}
}
结果显然是流而不是 json(从 Postman 复制):
data:{"timestamp":1558126555269,"result":"8"}
data:{"timestamp":1558132444247,"result":"10"}
data:{"timestamp":1558132477916,"result":"10"}
data:{"timestamp":1558132596327,"result":"14"}
堆栈基于 MongoDb 和 Spring 引导,但我不打算粘贴在这里,因为它不相关。
反应
async componentDidMount() {
const response = await fetch('http://localhost:8080');
const data = await response.json();
}
我得到 "Uncaught (in promise) SyntaxError: Unexpected token d in JSON at position 0" 的原因很明显:我不是 return 有效的 json。
然后,如果我将 Webflux 控制器更改为生成 json(生成 = MediaType.APPLICATION_JSON_VALUE),其余控制器对我的回答既不是流也不是无阻塞代码的结果。
[
{
"timestamp": 1558126555269,
"result": "8"
},
{
"timestamp": 1558132444247,
"result": "10"
},
{
"timestamp": 1558132477916,
"result": "10"
},
{
"timestamp": 1558132596327,
"result": "14"
}
]
有了这样的答案,React 前端可以解析,但我知道我没有利用流式处理。有人可能会争辩说,对于这样一个简单的例子,在流媒体中思考是没有价值的,但我的学习目的实际上是集中在使用 webflux + react consumming streams 正确理解和编码。
最后,在阅读 https://spring.io/blog/2017/02/23/spring-framework-5-0-m5-update 之后,我将 webflux restcontroller 更改为生成 APPLICATION_STREAM_JSON_VALUE 并且我还尝试生成 = "application/stream+json"。对于这两个尝试,restcontroller 的回答似乎是 json 的流,但 React 再次抱怨:
{"timestamp":1558126555269,"result":"8"}
{"timestamp":1558132444247,"result":"10"}
{"timestamp":1558132477916,"result":"10"}
{"timestamp":1558132596327,"result":"14"}
React 端错误:
Unexpected token { in JSON at position 41
总而言之:我没有发现如何从 React 使用 Webflux Restcontroller 来生成 Json.
的流
可能的答案可能是 "change React by using this library and consume that way" 或者答案可能是 "code Webflux Restcontroller to return in that format"。顺便说一句,在阅读了我在 React + Webflux 主题下找到的所有示例后,我被卡住了。
换句话说,我的直截了当的问题是:如何使用 webflux 端点从 React 生成 json 流?
服务器正在按预期生成单个 JSON 字符串流;但是,客户端在一个请求中收到它们。
也就是说,客户端正在尝试解析 { id: 1 } { id: 2 }
并在第二个 {
上失败。
如果您切换服务器以生成 APPLICATION_JSON
,服务器将接收集合 [{ id: 1 }, { id:2 }]
,它应该可以工作。
您是否尝试过使用 EventSource 来消费流?
回复有点晚,希望对你有帮助。
const source = new EventSource('/api-stream-endpoint');
source.onmessage = function logEvents(event) {
console.log(JSON.parse(data));
}
我想了解如何使用 WebFlux restcontroller 从 React 生成 json 流。我的第一个尝试迫使我解析为 json 的文本 instetad,但我觉得我在做一些奇怪的事情。我决定投入精力阅读周围的例子,我发现了一个例子 returning org.reactivestreams.Publisher 而不是 returning WebFlux。
我发现了一个有点老的话题可以帮助我 (Unable to Consume Webflux Streaming Response in React-Native client),但它没有一个答案。好吧,这促使我去某个地方读到 React 可能不符合 Reactive 但这是一个非常古老的 post.
从网上拿个例子,如果你看https://developer.okta.com/blog/2018/09/25/spring-webflux-websockets-react基本上你会发现:
WebFlux 产生 Json 但不流式传输:
RestController producing MediaType.APPLICATION_JSON_VALUE and returning org.reactivestreams.Publisher<the relevant pojo>
反应消耗 json:
async componentDidMount() {
const response = await fetch('relevant url');
const data = await response.json();
}
我尝试过类似的方法,但有两个显着差异:
我正在 returning MediaType.TEXT_EVENT_STREAM_VALUE 因为我相信我应该更喜欢 return 流,因为我正在使用无阻塞代码,而不是 returning org.reactivestreams.Publisher 我理解 return Webflux 更有意义,以便正确利用 Spring 5+.
我的 Webflux 休息控制器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.mybank.web.model.Loans;
import com.mybank.web.service.LoansService;
import reactor.core.publisher.Flux;
@RestController
public class LoansController {
@Autowired
private LoansService loansService;
@CrossOrigin
@RequestMapping(method = RequestMethod.GET, produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ResponseBody
public Flux<Loans> findAll() {
Flux<Loans> loans = loansService.findAll();
return loans;
}
}
结果显然是流而不是 json(从 Postman 复制):
data:{"timestamp":1558126555269,"result":"8"}
data:{"timestamp":1558132444247,"result":"10"}
data:{"timestamp":1558132477916,"result":"10"}
data:{"timestamp":1558132596327,"result":"14"}
堆栈基于 MongoDb 和 Spring 引导,但我不打算粘贴在这里,因为它不相关。
反应
async componentDidMount() {
const response = await fetch('http://localhost:8080');
const data = await response.json();
}
我得到 "Uncaught (in promise) SyntaxError: Unexpected token d in JSON at position 0" 的原因很明显:我不是 return 有效的 json。
然后,如果我将 Webflux 控制器更改为生成 json(生成 = MediaType.APPLICATION_JSON_VALUE),其余控制器对我的回答既不是流也不是无阻塞代码的结果。
[
{
"timestamp": 1558126555269,
"result": "8"
},
{
"timestamp": 1558132444247,
"result": "10"
},
{
"timestamp": 1558132477916,
"result": "10"
},
{
"timestamp": 1558132596327,
"result": "14"
}
]
有了这样的答案,React 前端可以解析,但我知道我没有利用流式处理。有人可能会争辩说,对于这样一个简单的例子,在流媒体中思考是没有价值的,但我的学习目的实际上是集中在使用 webflux + react consumming streams 正确理解和编码。
最后,在阅读 https://spring.io/blog/2017/02/23/spring-framework-5-0-m5-update 之后,我将 webflux restcontroller 更改为生成 APPLICATION_STREAM_JSON_VALUE 并且我还尝试生成 = "application/stream+json"。对于这两个尝试,restcontroller 的回答似乎是 json 的流,但 React 再次抱怨:
{"timestamp":1558126555269,"result":"8"}
{"timestamp":1558132444247,"result":"10"}
{"timestamp":1558132477916,"result":"10"}
{"timestamp":1558132596327,"result":"14"}
React 端错误:
Unexpected token { in JSON at position 41
总而言之:我没有发现如何从 React 使用 Webflux Restcontroller 来生成 Json.
的流可能的答案可能是 "change React by using this library and consume that way" 或者答案可能是 "code Webflux Restcontroller to return in that format"。顺便说一句,在阅读了我在 React + Webflux 主题下找到的所有示例后,我被卡住了。
换句话说,我的直截了当的问题是:如何使用 webflux 端点从 React 生成 json 流?
服务器正在按预期生成单个 JSON 字符串流;但是,客户端在一个请求中收到它们。
也就是说,客户端正在尝试解析 { id: 1 } { id: 2 }
并在第二个 {
上失败。
如果您切换服务器以生成 APPLICATION_JSON
,服务器将接收集合 [{ id: 1 }, { id:2 }]
,它应该可以工作。
您是否尝试过使用 EventSource 来消费流? 回复有点晚,希望对你有帮助。
const source = new EventSource('/api-stream-endpoint');
source.onmessage = function logEvents(event) {
console.log(JSON.parse(data));
}