【问题标题】:ngrx - chain two store.select slicesngrx - 链接两个 store.select 切片
【发布时间】:2017-11-13 16:13:33
【问题描述】:

在我的 Todo Cmp 中有这段代码

this.todoListGroup$ = this.ngrx.select(fromRoot.getTodos)
    .flatMap((todos: Todo[]) => {
        console.log(todos)
        this.todos = todos
        this.ngrx.select(fromRoot.getLastChangedTodo);
    })
    .map(lastTodo =>{{
        console.log(lastTodo)
        doSomething(this.todos, lastTodo)
    })

当我订阅它时,每次待办事项更改时,我都会多获得一个 console.log(lastTodo)。我认为使用 flatmap 和 ngrx.select,我每次都订阅一个新的 Observable?

我可以使用哪个运算符链接两个存储切片?

编辑:

只要视图在 DOM 中,我就想继续订阅 todoListGroup$,因为它应该不断更新我的视图。

到目前为止,我的解决方案是在 reducer 中定义一个新切片,它返回两个所需的属性。但是,我仍然对哪个运算符可以有效地链接 ngrx 单个属性切片感兴趣。

谢谢!

【问题讨论】:

  • 你能澄清你的目标吗?如果您不想要多个内部订阅,我认为您想要 switchMapwithLatestFrom 如果您想要来自商店的两个值,但第一个应该是唯一的触发器。
  • 我发布的 2 个解决方案没有实现这一点是否有原因?
  • 抱歉,还没有尝试过 :) 到目前为止,我一直在自己工作。但是 withLatestFrom 似乎很有希望!谢谢
  • 您可能有兴趣使用reselect 库或仅使用原始rxjs 创建投影,而不是“在reducer 中定义一个返回两个所需属性的新切片”。这是使用 ngrx 创建投影的教程:gist.github.com/btroncone/…

标签: angular rxjs ngrx


【解决方案1】:

这是一种使用 combineLatest 运算符的 RxJs v6+ 方法。

首先像这样导入操作符和Observable函数:

import { Observable, combineLatest } from 'rxjs';
import { tap } from 'rxjs/operators';

然后你可以像这样使用它们:

combineLatest([
  this.store.pipe(select('users', 'userList')),
  this.store.pipe(select('users', 'accountsList')),
]).pipe(tap(([userList, accountsList]) => console.log(userList, accountsList)))

【讨论】:

  • CombineLatest 现在应该是一个商店选择数组。
  • 我已将答案更新为商店选择数组。
【解决方案2】:

这样的工作是否可行:

this.todoListGroup$ =
    Observable.combineLatest(
        this.ngrx.select(fromRoot.getTodos), 
        this.ngrx.select(fromRoot.getLastChangedTodo)
    )
    .do(([todos, lastToDo]) => console.log(todos, lastToDo));

do 将在每次更新getTodosgetLastChangedTodo任一 时执行,并在更新时从它们中的每一个中获取最新的已知值。这里需要注意的是,每个更新被触发的顺序可能并不总是相同的。因此,如果您想要更多的链式(或级联)更新,那么您可以这样做:

this.todoListGroup$ =
    this.ngrx.select(fromRoot.getTodos)
    .withLatestFrom(this.ngrx.select(fromRoot.getLastChangedTodo))
    .do(([todos, lastToDo]) => console.log(todos, lastToDo));

这将在每次更新 getToDos 时执行,并从 getLastChangedTodo 获取最新值。因此,链式(或级联)更新的习语。

编辑 rxjs 5+ 语法:

this.todoListGroup$ =
    combineLatest(
        this.ngrx.select(fromRoot.getTodos), 
        this.ngrx.select(fromRoot.getLastChangedTodo)
    )
    .pipe(tap(([todos, lastToDo]) => console.log(todos, lastToDo)));


this.todoListGroup$ =
    this.ngrx.select(fromRoot.getTodos).pipe(
      withLatestFrom(this.ngrx.select(fromRoot.getLastChangedTodo)),
      tap(([todos, lastToDo]) => console.log(todos, lastToDo))
    );

【讨论】:

  • so combineLatest 创建一个新的 Observable,每次组合的单个 Observable 发射时都会发射?
  • 是的,每次它们中的任何一个发出时,它都会为您提供两者的最新值
  • 注意:这种方式不使用最新版本的rxjs。在撰写本文时,当前版本为 6.0
【解决方案3】:

试试这个:

this.todoListGroup$ = this.ngrx.select(fromRoot.getTodos)
.flatMap((todos: Todo[]) => {
    console.log(todos)
    this.todos = todos
    this.ngrx.select(fromRoot.getLastChangedTodo);
})
.take(1)
.map(lastTodo =>{{
    console.log(lastTodo)
    doSomething(this.todos, lastTodo)
})

【讨论】:

  • 所以基本上我仍然每次都订阅一个新切片,但它在一个发射后完成?如果我不想完成它怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 2014-07-15
相关资源
最近更新 更多