Spring boot 2 WebFlux generate Json stream in the new version
for example
@GetMapping(value = "stream", produces = APPLICATION_STREAM_JSON_VALUE)
public Flux<Data> stream() {
return Flux.interval(Duration.ofSeconds(1)).map(Data::new);
}
will produce issuing new data every one second
{"value":"1"}
{"value":"2"}
{"value":"3"}
{"value":"4"}
{"value":"5"}
{"value":"6"}
i have tried angular 5 httpclient
findAll(): Observable<Data> {
return this._http.get<Data>(this.url);
}
but it not work for me as i want to be reactive it not send me the result as it cache the result until the connection colsed
I want to ask what is the best way to handle this Json in angular 5
As far as I know there is still no official solution (19.08.2018), however I have found some workaround. Each method of a HttpClient
has config
argument, where you can pass responseType
and other things. I have mixed those settings like bellow:
{observe: 'events', responseType: 'text', reportProgress: true}
Then you will receive events with given types, in range 0 to 4. At least in my case type
3 was interesting content, which was in field partialText
, but warning - in your case those messages (in partialText
field) will look like bellow:
1 message:
{"value":"1"}
2 message:
{"value":"1"}
{"value":"2"}
3 message
{"value":"1"}
{"value":"2"}
{"value":"3"}
etc... so, I have managed it like bellow:
method(url, /*if post - body,*/
{observe: 'events', responseType: 'text', reportProgress: true})
.pipe(
filter(e => e.type === 3 && e.partialText),
map(e => {
const partials = e.partialText.trim().split('\n');
return JSON.parse(partials.pop());
})
);
A browser client has no way to consume a JSON stream (application/stream+json) other than using Server-Sent Events or WebSocket.
With requirements and technology you have described, WebSocket is a better fit.
With Server-Sent Events, it can be done like that:
import * as EventSource from 'eventsource';
...
const eventSource = new EventSource("http://www.example.com/stream");
eventSource.onmessage = (event) => {
const data = JSON.parse(event['data']);
}
That is NDJson format. I managed handling it by doing this:
let handled = 0
http.get<any>("http://localhost:9000/myapi", {
observe: "events",
reportProgress: true,
responseType: "text" as "json",
}).pipe(
filter((e: any) => e.type === HttpEventType.DownloadProgress && e.partialText),
map(e => e.partialText.trim().split("\n"))
).subscribe((arr) => {
for (let i = handled; i < arr.length; i++) {
try {
console.log(JSON.parse(arr[i])) // Do obs.next(obj) here
handled = i + 1
} catch (e) { }
}
})
You can wrap that code in an Observable and make obs.next(JSON.parse(arr[i]))
where the console.log
is at.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With