将初始流与修改流与RxJS组合

时间:2016-06-29 13:01:29

标签: angular reactive-programming rxjs

我正在尝试将功能反应化,并将页面上的元素列表设置为流。这是使用Angular2但问题应该类似于任何基于流的架构。所以,我目前有两个流,初始流(用于从github获取用户列表的http调用)和删除用户流(在单击删除用户按钮时发生)。我相信大理石图如下所示:

|[user1,user2,user3]|                       <--- http initial stream
|---------------------x----------x-----...  <--- x denotes user removed

如何组合这些流来实现这一点?我后来也想到有更多的流进行排序和排序。我是以正确的方式来做这件事的吗?这是代码(注意这段代码不完整,目前removeUser $与用户$不是互动的):

export class UserGridComponent implements OnInit { 
    public users$: Observable<any>;
    public removeUser$: Subject;

    constructor(private _githubUserService: GithubUserService) { }

    ngOnInit() { 
       this.removeUser$ = new Subject()
           .subscribe((user) => { console.log('next ' + JSON.stringify(user)});
       this.users$ = this._githubUserService.getUsers()
           .map((res) => res.json());
    }
}
  

以下是Plunker

目前我只是登录到控制台,点击了删除按钮并传递了用户。

这是html模板,显示我使用异步管道(Angular2)订阅用户$:

<md-list>
  <h1 md-header>GitHub Users</h1>
  <md-list-item *ngFor="let user of users$ | async">
    <a href="https://github.com/{{user.login}}" target="_new">
      <img md-list-avatar [src]="user.avatar_url">
    </a>
    <h4>{{user.login}}</h4>
    <button md-icon-button (click)="removeUser$.next(user)">
      <md-icon>cancel</md-icon>
    </button>
  </md-list-item>
</md-list>

2 个答案:

答案 0 :(得分:1)

ngOnInit() { 
   this.users$ = new BehaviorSubject([]); // init with empty user array
   this._githubUserService.getUsers()
       .map((res) => res.json())
       .subscribe(this.users$);

   this.removeUser$ = new Subject();
   this.removeUser$.subscribe((user) => { 
       this.users$.take(1)  // get current users, as users$ is a BehaviorSubject
           .map(users => users.filter(u => u != user))   // remove `user`
           .subscribe(this.users$); // update users$ stream
   });
}

希望我的评论可以作为解释。 BehaviorSubject缓存最后发出的值,因此this.users $ .take(1)是同步的。我发现自己使用BehaviorSubject作为angular2&#39;的来源。 |异步&#39;经常管道。

编辑:相同的想法,但removeUser$部分更短:

.....
   this.removeUser$.withLatestFrom(user$, 
       (toRemove, users) => users.filter(u => u != toRemove)   // remove `toRemove`
   ).subscribe(this.users$); // update users$ stream

答案 1 :(得分:0)

看看这个堆叠闪电战:它展示了如何使用scan来改变一个或多个来源发出的事件对单个值(可以是任何值)的突变。在该示例中,所有传入操作都来自Modify $流,但是您也可以将add $和remove $流合并在一起。

https://stackblitz.com/edit/angular-evc48h

但是...我不建议您这样做,因为这正是国家存储为您服务的。

因此,请务必查看著名的ngrx: https://github.com/ngrx/platform

或者鲜为人知但更清晰的ngxs: https://github.com/ngxs/store

我经常听到人们声称使用状态存储会引入不必要的复杂性,这对于小而简单的屏幕可能是正确的。但是,屏幕越复杂,状态存储就越能帮助您保持屏幕的优雅和整洁。