4

我对 rxjs 运算符有点困惑delay

当我使用创建的假 observable 对其进行测试时from,我只会看到一个初始延迟:

const { from } = Rx;
const { delay, tap } = RxOperators;

from([1, 2, 3, 4]).pipe(
  tap(console.log),
  delay(1000));

(您可以将此代码段复制并粘贴到rxviz中。)

我在其中放置了一个tap以确保from实际将数组项作为单独的值而不是单个数组值发出。

最初的延迟不是我所期望的,但至少文档是这样说的:

[...] 这个操作符时间将源 Observable 移动了以毫秒表示的时间量。值之间的相对时间间隔被保留。

但是,当我使用从事件创建的 observable 对其进行测试时,我会在每个发出的值之前看到一个延迟:

const { fromEvent } = Rx;
const { delay } = RxOperators;

fromEvent(document, 'click')
  .pipe(delay(1000))

这里发生了什么?为什么delay在这两种情况下表现不同?

4

3 回答 3

10

所做的一切delay就是它所说的:每当它接收到一个值时,它会在延迟期间保持该值,然后发出它。它对接收到的每个值执行相同的操作。 delay不会更改流项目之间的相对时间。

所以,当你这样做时from([1,2,3,4]).pipe(delay(1000)),会发生什么:

  • 时间 0:from发出 1
  • 时间 0:delay看到 1 并启动 timer1
  • 时间 0:from发出 2
  • 时间 0:delay看到 2 并启动 timer2
  • ...
  • 时间 1000:timer1 完成并delay发出 1
  • 时间 1000:timer2 完成并delay发出 2
  • ...

因此,因为所有 4 个值都是快速连续发出的,所以您实际上只会看到一个初始延迟,然后所有 4 个值都会向下游发出。实际上,每个值都比最初发出时延迟了 1 秒。

如果您想“分散”这些项目,使它们至少相隔 1 秒,那么您可以执行以下操作:

const source = from([1, 2, 3, 4])
const spread = source.pipe(concatMap(value => of(value).pipe(delay(1000))));
spread.subscribe(value => console.log(value));

这会将每个单独的值转换为一个可观察值,该可观察值会在延迟后发出该值,然后连接这些可观察值。这意味着每个项目的计时器在前一个项目的计时器完成之前不会开始计时。

于 2019-07-09T18:11:54.283 回答
1

在第一个代码片段中,您逐个元素地发出数组元素。首先延迟,然后处理数组元素。

'from' 和 'pipe' 使 'delay' 执行一次。管道序列处理,首先延迟,然后点击,点击,点击,点击。

在第二个代码片段中,您正在发射对象(它们到达),因此每个对象都会发生一次延迟。

'fromEvent' 和 'pipe' 使每个事件“延迟”。管道序列处理每个事件之前的延迟。

于 2019-07-08T16:36:27.247 回答
1

您点击流并获取发出的值,然后将它们传送到延迟中,延迟一秒钟后发出它们。管道中的每个函数都返回一个新的 observable,它向管道中的下一个函数发出一个值。Tap 返回尚未延迟的相同可观察对象,延迟返回一秒后发出的可观察对象。

const { from } = rxjs;
const { delay, tap } = rxjs.operators;

from([1, 2, 3, 4]).pipe(
  tap(val => { console.log(`Tap: ${val}`); }),
  delay(1000)).subscribe(val => { console.log(`Sub: ${val}`); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js"></script>

如果您在延迟后点击,那么您会在延迟后看到它们。

const { from } = rxjs;
const { delay, tap } = rxjs.operators;

from([1, 2, 3, 4]).pipe(
  delay(1000),
  tap(val => { console.log(`Tap: ${val}`); })).subscribe(val => { console.log(`Sub: ${val}`); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js"></script>

于 2019-07-08T23:07:49.527 回答