RxJS 6 /点击运算符何时发出值
Posted
技术标签:
【中文标题】RxJS 6 /点击运算符何时发出值【英文标题】:RxJS 6 / When does tap operator emit a value 【发布时间】:2019-04-16 09:25:44 【问题描述】:我一直在想是否可以安全地假设在使用 tap 操作符之后,它内部的副作用已经完成。
我的用例是ngrx。
...
tap(() =>
this.store.dispatch(new SetValue("Hello World"));
),
switchMap(() => this.store),
select(state => state.value),
tap(state =>
if (state === undefined)
throw new Error("Couldn't find value");
)
SetValue是一个实现ngrx的类
export class SetValue implements Action
readonly type = SET_VALUE;
constructor(public payload: string)
我正在尝试实现的是在商店中设置一个值,然后检查它是否已有效设置。
我可以假设在点击操作符之后调度已经完成吗?
回答
我在 Angular Router guards 上使用它通过 url 上的参数设置初始状态,所以我最终过滤为仅在商店有新值时继续
...
tap(() => this.store.dispatch(new SetValue("Hello World"))),
switchMap(() => this.store),
select(state => state.value),
filter(value => value === "Hello World"),
take(1)
【问题讨论】:
我对我的代码的思考过于迫切,我对任何遇到此问题的人的建议是鼓励反应式编程,考虑蒸汽以及何时发送数据 【参考方案1】:RxJS 中的大多数操作都是同步的,所以如果 this.store.dispatch(new SetValue("Hello World"))
不执行任何异步任务,它可能会按预期工作(它仍然只是一个主题)。
但是,您不应依赖此行为。 NgRx 可能会改变它的内部结构,通常最好不要依赖 RxJS 运算符的同步/异步(这在过去已经发生过,例如 from()
从 RxJS 4 到 RxJS 5)。
如果您想确保已设置某些内容,请更改您的 new SetValue("Hello World")
效果以在完成所需操作后发出另一个操作。
【讨论】:
SetValue 是一个实现来自ngrx的动作的类,你的建议如何适应?export class SetValue implements Action readonly type = SET_VALUE; constructor(public payload: string)
你可能会在另一个效果中处理这个动作,因为我猜你没有创建一个什么都不做的动作。因此,当它处理完 SetValue
动作后,您将其映射到另一个动作,告诉您 SetValue
已完成。
我正在将问题编辑为现实世界的问题。我正在尝试使用基于 url 的 RouteGuard 为商店提供值。那是动作调度的地方。我想检查商店中的值是否已成功填写,否则重定向到另一个页面
除了@martin 所说的,ngrx 也建议我们这样做。根据加载/设置操作发出成功/失败操作。然后,您可以收听由 Success/Fail 操作更新的加载/错误状态并决定离开。
为了完整起见,我最终在点击旁边过滤(rxjs 过滤器运算符),以确保商店更改了值。【参考方案2】:
tap
运算符接受 3 个参数。
1- 如果源 observable 发出一个值,tap
运算符的第一个参数是一个函数,该函数接收该发出的值作为参数。
2- 如果源 observable 进入错误状态,tap
运算符的第二个参数是一个接收该错误作为参数的函数。所以在这里你可以调度错误。
3- 第三个参数是一个函数,只要 observable 被标记为完成,就会调用该函数。
tap(observer, error, complete):Observable
【讨论】:
以上是关于RxJS 6 /点击运算符何时发出值的主要内容,如果未能解决你的问题,请参考以下文章
如何在不需要 rxjs-compat 的情况下只导入 RxJS 6 中使用的运算符,如旧的 RxJS?
如何使用jasmine-marbles测试rxjs管道中的timeout()
如何基于另一个 Observable 重置 RXJS 扫描算子