我正在寻找改进下面代码的想法,我将从描述问题开始,并提出我希望改进的解决方案。
代码是Angular 4(TS)
herelistOfItems$: Observable<Array<Item>>;
// Getting list of items from the backend
init() {
this.listOfItems$ = http.get('/getItems');
}
// - Check if item already exits (show error and stop if exists)
// - If not add the item (http request)
// - Refresh by getting get the updated list from the backend (http request)
onClickAddNewItem(newItem: Item) {
this.listOfItems$ = this.listOfItems$
.filter(/* validate item is not exits */)
.concatMap(_ => http.post('/addItem', newItem))
.switchMap(_ => http.get('/getItems'))
.catch((err) => ...);
}
HTML代码看起来像
<div *ngFor="let item of listOfItems$ | async">...
此代码的问题是重复分配this.listOfItems$ = this.listOfItems$...
一种可能的解决方案是
onClickAddNewItem(newItem: Item) {
this.listOfItems$
.filter(/* validate item is not exits */)
.concatMap(_ => http.post('/addItem', newItem))
.subscribe(_ => this.listOfItems$ = http.get(...), err => ... );
}
我正在寻找一种更优雅的方式刷新列表而不订阅它,任何想法? (我知道我可以用ngrx \ store解决它但我不能在这个项目中使用它)
感谢您的帮助
答案 0 :(得分:2)
您可以从通常运行onClickAddNewItem
的点击事件中创建一个可观察的流。
@ViewChild() addButton;
this.listOfItems$ = this.http.get('/getItems').pipe(
switchMap(items => fromEvent(this.addButton.nativeElement, 'click').pipe(
startWith(items),
filter(/* ... */)
mergeMap(newItem => this.http.post('/addItem', { newItem })),
switchMap(() => this.http.get('/getItems')),
),
);