I'm trying to understand a few things about RxJs. What I would like to do is consume some JSON data and immediately begin to render that data on the DOM as it's coming in. I've setup the stream request, response, and display. It's outputting every just fine but it's doing it all at once and not over time.
I want to start showing the data on the page as its coming in, instead of waiting for the whole file to complete then show at once which would create a long wait time.
//Cache the selector
var $resultList = $('.results');
//Gets the JSON (this will not be a static file,just for testing)
var requestStream = Rx.Observable.just("/results.json");
var responseStream = requestStream
.flatMap(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl))
});
var displayStream = responseStream.subscribe(
function(response) {
//This maps to a Handlebars Template and puts it on the DOM
$resultList.html(compiledTemplate(response));
},
function(err) {
console.log('Error: %s', err);
},
function() {
console.log('Completed');
});
//Sample of the data from the JSON file
Object{
beginIndex: "1"
catId: "111"
endIndex: "1"
products: Array[100]
}
If I understand well, there are two relevant points to make:
- you need to find a way to have a stream of objects from that file
instead of one big object when you finish reading that file (
I want
to start showing the data on the page as its coming in
). The
mechanics of that would depend first on the structure of the source (file and file reading mechanism)
than on Rxjs (is every line an object that can lead to information
display etc.?). Once you have that 'minimum displayable unit of information' you can use Rxjs to buffer/process it if need be (do you want to display something for each object, or each 100 objects, or remove uncessary attributes etc.?)
- you need to update your display incrementally
as new data arrive. That means you need something like
$resultList.html($resultList.html() + compiledTemplate(response));
to append the new compiled html
to the old one.
UPDATE : for chunking an array, you can have a look at this jsfiddle : http://jsfiddle.net/429vw0za/
var ta_result = document.getElementById('ta_result');
function emits ( who, who_ ) {return function ( x ) {
who.innerHTML = [who.innerHTML, who_ + " emits " + JSON.stringify(x)].join("\n");
};}
function fillArrayWithNumbers(n) {
var arr = Array.apply(null, Array(n));
return arr.map(function (x, i) { return {prop1: i, prop2:i, prop3:i} });
}
var sampleObj = {
beginIndex: "1",
catId: "111",
endIndex: "1",
products: fillArrayWithNumbers(100)
}
console.log('sampleObj', sampleObj);
var result$ = Rx.Observable
.from(sampleObj.products)
.bufferWithCount(10)
.map(function(mini_array){return {
beginIndex: sampleObj.beginIndex,
catId: sampleObj.catId,
endIndex: sampleObj.endIndex,
products: mini_array
}})
.do(emits(ta_result, 'result'));
result$.subscribe(function(){ });
You will then have a stream of objects with arrays of size 10 taken from the array of size 100.