Question 1
Here's an example implementing a function that calls itself when it gets a response.
Backend:
- Simulate a slow backend that responds within 5s and 10s
- At each response, the server gives the current
request_number
and a state
- For the 3 first responses, the
state
is active
, after that, the state
is closed
code:
/* Mocked backend. I'm slow, like really slow */
class SlowBackend {
MAX_ITERATIONS = 3; // suppose you're reading a table and you have pagination, with 3 pages
currentIteration = 0;
constructor() {}
getStuff() {
console.log(`**Request N. ${this.currentIteration}**\n[Back] : received a request from the front`);
const responseDelay = Math.random() * 5000 + 5000; // response between 5s and 10s
let state = "open";
if(++this.currentIteration > this.MAX_ITERATIONS)
state = "closed";
return Observable
.timer(responseDelay)
.map( () => {
console.log(`[Back] : Responding after ${responseDelay} ms`)
return {
request_number : this.currentIteration,
state : state
};
})
}
}
Front:
This is basically your component.
class Frontend {
isPollingActivated = true;
responses = [];
constructor(private backendService) {
this.backendService = new SlowBackend(); // connection to backend
this.requestOnRegularBasis();
}
requestOnRegularBasis() {
if (!this.isPollingActivated)
return;
this.backendService.getStuff()
.subscribe(response => {
console.log(`[Front] : received response from server. State : ${response.state}`);
// Choose one of the following blocks, comment the other according to what you need
// Block 1 : Sync processing example
console.log(`[Front] : doing some sync processing`);
this.doSomeSyncProcessing(response);
this.requestOnRegularBasis();
// Block 2 : Async processing example
// console.log(`[Front] : doing some async processing`);
// this.doSomeAsyncProcessing(response)
// .subscribe(this.requestOnRegularBasis);
})
}
private doSomeSyncProcessing(response){
if(response.state == 'closed'){
this.isPollingActivated = false; // stop polling
this.saveDataToCsv();
}
else
this.responses.push(Object.values(response).join(';')) // csv line separated by ';'
}
private saveDataToCsv(){
const headers = ['current_request;state']
this.responses = headers.concat(this.responses)
console.log('saving to csv : ', this.responses.join('\n'));
// Uncomment this to use FileSaver API
/*
const blob = new Blob(headers.concat(this.responses), {type: "text/csv;charset=utf-8"});
saveAs(blob, "my_responses.csv");*
*/
}
private doSomeAsyncProcessing(response){
return Observable.timer(1000).map(() => this.doSomeSyncProcessing(response));
}
}
output:
**Request N. 0**
[Back] : received a request from the front
[Back] : Responding after 5482 ms
[Front] : received response from server. State : open
[Front] : doing some sync processing
**Request N. 1**
[Back] : received a request from the front
[Back] : Responding after 7489 ms
[Front] : received response from server. State : open
[Front] : doing some sync processing
**Request N. 2**
[Back] : received a request from the front
[Back] : Responding after 9627 ms
[Front] : received response from server. State : open
[Front] : doing some sync processing
**Request N. 3**
[Back] : received a request from the front
[Back] : Responding after 5806 ms
[Front] : received response from server. State : closed
[Front] : doing some sync processing
saving to csv :
current_request;state
1;open
2;open
3;open
Question 2
You can't.
At least not using FileSaver
. Because it doesn't support writing chunk by chunk. When you instanciate your Blob
, you have to
have all your data ready.
There are some libraries that support chunks but they are either meant for server side (node.js for example), or extremely browser specific.
Check this : Save client generated data as file in JavaScript in chunks
Note :
if you are trying to store a 1M rows csv in client's machine using js, then maybe something is wrong with the architecture.
Because this is not a common usecase for browsers. Clients are supposed to have weak machines, an thus receive processed,
light, easy to parse information. For that matter, you can for example construct the csv in the server side which will
have all the rights to write stream files, and decent processing/memory capacity.
Demo : Question 1
http://jsbin.com/rojutudayu/2/edit?html,js,console
Demo : How to download the blob ?
<script src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"> </script>
<script>
var blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
saveAs(blob, "hello world.txt");
</script>