问题1
下面是一个实现函数的示例,该函数在收到响应时调用自身。
后端:
-
模拟5秒和10秒内响应缓慢的后端
-
在每次响应时,服务器都会给出
request_number
和A
state
-
对于3个第一反应,
状态
是
active
之后,
状态
是
closed
代码:
/* 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
};
})
}
}
前面:
这基本上是您的组件。
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));
}
}
输出:
**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
问题2
你不能。
至少不使用
FileSaver
. 因为它不支持逐块写入。当你宣布
Blob
你必须
准备好所有数据。
有些库支持块,但它们要么用于服务器端(例如node.js),要么非常特定于浏览器。
检查一下:
Save client generated data as file in JavaScript in chunks
注:
如果您试图使用JS在客户机中存储1百万行的csv,那么架构可能有问题。
因为这不是浏览器的常见用例。客户机应该有薄弱的机器,因此接收处理,
轻,易于分析信息。为此,您可以在服务器端构建csv,它将
拥有写入流文件的所有权利,以及适当的处理/内存容量。
演示:问题1
http://jsbin.com/rojutudayu/2/edit?html,js,console
演示:如何下载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>