rxjs observable - 避免递归赋值

时间:2018-05-11 20:01:04

标签: angular typescript rxjs observable ngrx

我正在寻找改进下面代码的想法,我将从描述问题开始,并提出我希望改进的解决方案。

代码是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解决它但我不能在这个项目中使用它)

感谢您的帮助

1 个答案:

答案 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')),
  ),
);