我正在学习Rxjs并希望自己尝试一些例子 但是,我似乎无法反省思考。
我正在尝试计算用户鼠标指针在div内外的时间。
请参阅小提琴 - https://jsfiddle.net/ishansoni22/44af3n3k/
<div class = "space">
<div>
let $space = $(".space")
let in$ = Rx.Observable.fromEvent($space, "mouseenter")
.map((event) => "in")
let out$ = Rx.Observable.fromEvent($space, "mouseleave")
.map((event) => "out")
let inOut$ = Rx.Observable.merge(in$, out$)
let time$ = Rx.Observable.interval(1000)
.buffer(inOut$)
.map((list) => list.length)
time$.subscribe((value) => console.log(value));
我能够计算时间但是如何将其与相应的输入/输出流相关联?我希望输出看起来像:
另外,有人能指出我可以做的一些例子,以便我可以开始考虑反应范式吗?
答案 0 :(得分:3)
官方文档中有一些例子(http://reactivex.io/rxjs)但确实有点稀缺。
我想我会给你的一些样本:
let $space = $(".space")
let in$ = Rx.Observable.fromEvent($space, "mouseenter")
let out$ = Rx.Observable.fromEvent($space, "mouseleave")
let durations$ = in$
.map(_ => Date.now())
.switchMap(inTime => out$
.take(1)
.map(_ => Date.now())
.map(outTime => outTime - inTime)
)
durations$
.scan((sum, next) => sum + next, 0)
.subscribe(total => console.log(total))
这将开始收听$,然后在mouseenter
- 事件中它开始收听mouseleaves
,接收其中一个事件并计算持续时间。
为了清楚起见,我在彼此之下写了多张地图,但当然你可以把它组成一个单一的功能。
答案 1 :(得分:1)
我开始使用Rx时遇到的最具挑战性的事情之一就是使用了溪流,并且对flatMap
和switchMap
感到满意。使用这种方法最容易解决您描述的问题。您的流定义如下(我更喜欢const
而不是let
,以明确没有发生突变):
const in$ = Rx.Observable.fromEvent($space, 'mouseenter');
const out$ = Rx.Observable.fromEvent($space, 'mouseleave');
您可以按如下方式描述进入然后离开:
const inThenOut$ = in$.switchMap(() => out$);
要准确了解这是做什么的,我建议您了解flatMap
,熟悉流媒体流,然后通过仅保留对最新内部流的订阅来了解switchMap
的工作原理。为此,我发现官方rxjs文档是最好的来源。包含的大理石图表通常只用几个点和线来表示复杂的故事。
从这里开始花费时间是相对较小的一步。首先,我们将原始流映射到时间戳值:
const timestamp = () => + new Date();
const in$ = Rx.Observable.fromEvent($space, 'mouseenter').map(() => timestamp());
const out$ = Rx.Observable.fromEvent($space, 'mouseleave').map(() => timestamp());
(注意:你可以使用rxjs中的timestamp
方法而不是手动执行此方法,但我觉得这更好地说明了如何将流元素映射到您喜欢的任何内容。
从那里,我们可以调整switchMap
用法来访问输入和输出值,并返回它们之间的差异:
const inThenOut$ = in$.switchMap(() => out$, (x, y) => y - x);
这是完整的工作:
答案 2 :(得分:0)
您可以使用RXJS - Timestamp operator将时间戳记附加到Observable发出的每个项目上,以指示何时发出。
const { fromEvent } = Rx;
const { map, switchMap, timestamp, take, tap } = RxOperators;
const in$ = fromEvent($space, 'mouseenter').pipe(
timestamp(),
tap(x => console.log(`In: ${x.timestamp}`))
)
const out$ = fromEvent($space, 'mouseleave').pipe(
timestamp(),
tap(x => console.log(`Out: ${x.timestamp}`))
)
const duration$ = in$.pipe(
switchMap(start => out$.pipe(
take(1),
map(finish => finish.timestamp - start.timestamp),
tap(value => console.log(`Duration ms: ${value}`))
)
)
)
/* output example
In: 1552295324302
Out: 1552295325158
Duration ms: 856
*/