2
這很困難。我是RxJs Observables的新手,所以需要一些指導。配置一個Observable,當一個新值被推入時,將所有以前的值作爲一個數組返回?
我想構建一個可以執行兩件事情的Observable日誌流。
- 每當將新行/值寫入日誌文件時,將該新值推送到流中。
- 開始預填充日誌文件中的值。
我完成了上述兩項標準。現在面臨的挑戰是使用* ngFor。
* ngFor需要來自Observable的數組,因此它可以比較添加/刪除(我最好的猜測)。但是我的observable只返回最後一個項目的數組。
//logviewer.page.ts constructor()
this.logs = Subject.create();
this.logs$ = this.logs.asObservable()
.startWith("logs\\error.log")
.flatMap((fileName: string) => {
//start by reading the existing log files as a string
return this.$localStorageService.readAsStringAsync(fileName);
})
.map((contents: string) => {
//this part splits up the log file line-by-line into an log entry
let logs = contents.split(/\r\n|\r|\n/).filter(n => n.length > 0);
logs.forEach((s, ix, parent) => {
let x = JSON.parse(s);
parent[ix] = { timestamp: new Date(parseFloat(x[0])), message: x[1] };
})
return logs; //an array of objects { timestamp, message }
})
//merge the existing application log stream
//throughout the application we log errors, info, etc
//if a new entry is made it will appear here
.merge(this.$loggerService.applicationLog$.map((x) => {
//return an array with one object { timestamp, message }
return [{ timestamp: new Date(parseFloat(x[0])), message: x[1] }];
}))
現在我的模板很簡單,現在。
//logviewer.template.ts
<div *ngFor="let entry of logs$ | async">
{{entry|json}}
</div>
我們測試了一下,我有一個按鈕添加一個條目
//logviewer.page.ts
addEntry() {
this.$loggerService.error("this is a test");
}
//LoggerService.service.ts
private applicationLog: ReplaySubject<any[]>;
get applicationLog$(): Observable<any[]> {
return this.applicationLog.asObservable();
}
error(...args) {
let data = [Date.now().toString()].concat(args.map<string>((n, ix) => { return toString(n); }));
// ... write to file
// fire the subject
this.applicationLog.next(data);
}
現在,當我點擊addEntry
,管道的所有作品,其值是通過觀察到的序列正確地解僱了。但是我的* ngFor只更新了一個值。它不保留所有以前的日誌條目的歷史記錄。只是返回的最後一個數組,這是有道理的。
如何讓我的可觀察序列始終返回所有值的數組。我可以讓它一次返回一個條目,但我需要完整的歷史才能滿足* ngFor
我對* ngFor和異步管道缺乏瞭解。我認爲它訂閱了observable,並自動添加任何新的條目到ngFor,但事實並非如此。
哇,太感謝你了。 – Matt