BufferTime带领先选项

时间:2019-03-28 17:58:00

标签: rxjs

我有一些要缓冲的事件,但是我只想在第一个元素之后缓冲。

[------bufferTime------]

Input over time:
[1, 2, 3, -------------|---4, 5, 6 ----------------]


Output over time:
[1]-----------------[2,3]---[4]------------------[5,6]

有没有办法做到这一点?

4 个答案:

答案 0 :(得分:2)

您可以使用multicast将流分成两部分,然后将第一个值传递通过。

import { concat, Subject } from “rxjs”;
import { multicast, take, bufferCount } from “rxjs/operators”;

source.pipe(
  multicast(
    new Subject(),
    s => concat(
      s.pipe(take(1)),
      s.pipe(bufferCount(X)),
    )
  ),
);

答案 1 :(得分:2)

我认为可以通过将流分成firstValue $和afterFirstValue $两个然后合并它们来解决。

import { merge } from 'rxjs';
import { take, skip, bufferTime } from 'rxjs/operators';

...

firstValue$ = source$.pipe(
  take(1)
);

afterFirstValue$ = source$.pipe(
  skip(1),
  bufferTime(5000)
);

merge(firstValue$, afterFirstValue$)
  .subscribe(result => {
    // Do something
  });

回答有关主题的问题

所以我这样做了,以便原始资料是这里的主题。并非完全按照您的描述来描述,但我想这也许就是您想要的。

  import { merge, Subject } from 'rxjs';
  import { take, skip, bufferTime } from 'rxjs/operators';
  import { Source } from 'webpack-sources';

  ...

  source$ = new Subject();

  firstValue$ = source$.pipe(
    take(1)
  );

  afterFirstValue$ = source$.pipe(
    skip(1),
    bufferTime(5000)
  );

  merge(firstValue$, afterFirstValue$)
    .subscribe(result => {
      // Do something
    });

  source$.next(1);
  source$.next(1);
  source$.next(1);

答案 2 :(得分:0)

我得到了很好的答案,启发了我对问题的看法,使我想出了我所需要的真实东西,就像这样:

function getLeadingBufferSubject (bufferTimeArg) {
    const source = new Subject()
    const result = new Subject()

    let didOutputLeading = false

    const buffered$ = source
        .pipe(bufferTime(bufferTimeArg))
        .pipe(filter(ar => ar.length > 0))
        .pipe(map(ar => [...new Set(ar)]))

    buffered$.subscribe(v => {
        didOutputLeading = false
        const slicedArray = v.slice(1)

        // emits buffered values (except the first)  and set flag to false
        if (.length > 0) result.next(v.slice(1))
    })

    // emits first value if buffer is empty
    source.subscribe(v => {
        if (!didOutputLeading) {
            didOutputLeading = true
             result.next(v)
        }
    })

    // call .next(value) on "source"
    // subscribe for results on "result"
    return {
        source,
        result
    }
}

答案 3 :(得分:0)

我遇到了同样的问题,在解决了这个问题之后,我发现了这个额外的解决方案:

source$.pipe(
  buffer(source$.pipe(
    throttleTime(bufferTime, asyncScheduler, {leading: true, trailing: true}),
    delay(10) // <-- This here bugs me like crazy though!
  )
)

由于throttle已经具有leading选项,因此您可以使用它手动触发缓冲区发射。

我真的很想在这里摆脱那个delay。这是必需的,因为首先触发内部的observable导致缓冲区过早发射。