Rxjs - 计算在div内部/外部花费的时间

时间:2017-05-04 08:39:45

标签: rxjs

我正在学习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)); 

我能够计算时间但是如何将其与相应的输入/输出流相关联?我希望输出看起来像:

  • inside,in - 20,out - 30
  • 外面,在 - 20,外面 - 35
  • inside,in - 100,out - 35

另外,有人能指出我可以做的一些例子,以便我可以开始考虑反应范式吗?

3 个答案:

答案 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时遇到的最具挑战性的事情之一就是使用了溪流,并且对flatMapswitchMap感到满意。使用这种方法最容易解决您描述的问题。您的流定义如下(我更喜欢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);

这是完整的工作:

https://jsbin.com/qoruyoluho/edit?js,console,output

答案 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
*/

在这里尝试:https://rxviz.com/v/rOW5g9x8