我对rxjs运算符delay
有点困惑。
当我使用from
创建的假可观察对象进行测试时,我只会看到 initial 延迟:
const { from } = Rx;
const { delay, tap } = RxOperators;
from([1, 2, 3, 4]).pipe(
tap(console.log),
delay(1000));
(您可以将此代码段复制并粘贴到rxviz中。)
我在其中放置了tap
,以确保from
实际上将数组项作为单独的值而不是单个数组值发出。
最初的延迟不是我所期望的,但是至少the docs所说的是:
[...]此运算符将源可观察的时间偏移以毫秒为单位的时间量。值之间的相对时间间隔被保留。
但是,当我使用从事件创建的可观察对象进行测试时,我会在每个发射值之前看到延迟 :
const { fromEvent } = Rx;
const { delay } = RxOperators;
fromEvent(document, 'click')
.pipe(delay(1000))
这是怎么回事?为什么delay
在两种情况下的行为都不一样?
答案 0 :(得分:2)
delay
所做的一切就是说:每当接收到一个值时,它将在延迟期间保持该值,然后发出该值。它对收到的每个值执行相同的操作。 delay
不会不更改流中项目之间的相对时间。
因此,当您执行from([1,2,3,4]).pipe(delay(1000))
时,会发生以下情况:
from
发出1 delay
看到1并启动timer1 from
发出2 delay
看到2并启动了timer2 delay
发出1 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));
这会将每个单独的值转换为可观察值,并在延迟后发出该值,然后将这些可观察值连接起来。这意味着每一项的计时器直到上一项的计时器完成后才会开始计时。
答案 1 :(得分:1)
在第一个代码段中,您逐个元素发射一个数组。首先延迟,然后处理数组元素。
'from'和'pipe'使'delay'执行一次。管道序列处理,先延迟,然后点击,点击,点击,点击。
在第二个代码段中,您正在发射对象(它们到达),因此每个对象发生一次延迟。
“ fromEvent”和“ pipe”使每个事件“延迟”。每个事件之前的延迟的管道序列处理。
答案 2 :(得分: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>