我正试图找到一个行为类似于concatMap
的运算符,但是将两者之间的所有内容都删除。例如,concatMap执行以下操作:
- 下一个
- 开始处理
- 下一个b
- 下一个c
- 完成处理
- 开始处理b
- 完成处理b
- 开始处理c
- 完成处理c
相反,我正在寻找一种将丢弃b
的机制,因为c
已经出现:
- 下一个
- 开始处理
- 下一个b
- 下一个c
- 完成处理
- (跳过b)
- 开始处理c
- 完成处理c
有关更多扩展的示例,请参见以下要点:https://gist.github.com/Burgov/afeada0d8aad58a9592aef6f3fc98543
答案 0 :(得分:2)
我认为您要寻找的运营商是throttle
。
这里是工作中的Stackblitz。进行此工作的关键是设置配置对象,该配置对象将传递给throttle()
,以使其能够{{1}发射和处理前导和尾随源发射,但忽略其间的任何发射。 }}正在运行。
这是Stackblitz的关键功能:
processData()
又矮又甜,除了一个问题外,它都能按要求工作...
上面的代码的“一个问题”是,当可观察到的源代码完成时,// Use 'from' to emit the above array one object at a time
const source$ = from(sourceData).pipe(
// Simulate a delay of 'delay * delayInterval' between emissions
concatMap(data => of(data).pipe(delay(data.delay * delayInterval))),
// Now tap in order to show the emissions on the console.
tap(data => console.log('next ', data.emit)),
// Finally, throttle as long as 'processData' is handling the emission
throttle(data => processData(data), { leading: true, trailing: true }),
).subscribe()
取消订阅processData,从而有效地停止了所有需要完成的最终处理。正如Bart van den Burg在下面的评论中指出的那样,解决方法是使用主题。我认为有很多方法可以做到这一点,但是Stackblitz已更新为现在可以运行的以下代码:
throttle()
答案 1 :(得分:1)
这是我最简单的解决方案:
const source = new Subject();
const start = new Date();
const mockDelayedObs = val => of(val).pipe(delay(1200));
source.pipe(
multicast(
new ReplaySubject(1),
subject => {
let lastValue;
return subject.pipe(
filter(v => v !== lastValue),
exhaustMap(v => {
lastValue = v;
return mockDelayedObs(v);
}),
take(1),
repeat(),
);
}
),
)
.subscribe(v => {
console.log(new Date().getTime() - start.getTime(), v);
});
setTimeout(() => source.next(0), 0);
setTimeout(() => source.next(1), 500);
setTimeout(() => source.next(2), 1000);
setTimeout(() => source.next(3), 1500);
setTimeout(() => source.next(4), 1800);
setTimeout(() => source.next(5), 4000);
实时演示:https://stackblitz.com/edit/rxjs-z33jgp?devtoolsheight=60
动作顺序是这样的:
next 0
start handling 0
next 1
next 2
finish handling 0
start handling 2
next 3
next 4
finish handling 2
start handling 4
finish handling 4
start handling 5
finish handling 4
因此只能打印0、2、4和5
这也不需要multicast
运算符,但我想避免泄漏状态变量。没有它们似乎不可能完全实现,因此只有一个lastValue
。此变量仅用于在用mockDelayedObs
重新订阅同一链之后,忽略两次为同一值调用repeat()
。
答案 2 :(得分:0)
也许您可以在对race
执行b
之后立即尝试在c
和mergeMap
上使用a
方法?
我看起来像这样:
a.pipe(
mergeMap(AResult => {
// store aResult
return race(b,c)
}
).subscribe(
finalResult => {
// final result corresponding to either b or c
}
)
如果您已经定义了要在a
之后执行的通话,则可以使用此功能。
答案 3 :(得分:0)
Ph,这很难破解:
https://stackblitz.com/edit/angular-yk7akk
所以基本上,我创建了2个可观察对象:
concatMap然后对这两个可观察对象进行合并。.
它按描述的方式工作,但它不完全是一种简单或直接的方法(命令性代码气味)。我一直在关注此讨论,以寻求更优雅的解决方案。