rxjs mergemap_rxjs和mergemap switchmap和exhaustmap之间的区别

rxjs mergemap

These four operators can often confuse new developers as the difference between them is minute, but very important!

这四个操作员通常会使新开发人员感到困惑,因为它们之间的差别很小,但是非常重要!

It all boils down on how the inner observable reacts when a new value comes in from the outer observable.

一切都归结为当外部观察值产生新值时内部观察值如何React。

准备工作 (Preparations)

What does all this mean? Let’s create a simple example. The difference only comes up if we let time pass so lets craft an example where we want to make a pipeline which receives timestamps, immediately emits that the timestamp is older than the current time, then it should emit again, once it expired.

这是什么意思呢? 让我们创建一个简单的示例。 仅当我们让时间流逝时,差异才会出现,因此让我们举个例子,我们要制作一个接收时间戳的管道,立即发出时间戳早于当前时间的消息,然后在到期后再次发出。

First, set up the core logic of this in a separate function. We know that the only thing we are working with is a timestamp and that we want to craft an observable that only emits boolean so lets do that.

首先,在单独的功能中设置其核心逻辑。 我们知道,我们正在使用的唯一东西是时间戳,并且我们想制作一个仅发出boolean的可观察对象,所以让我们这样做。

If the timestamp is already expired, no timer is needed so instead of over-complicating things just return an observable that will emit only a single true .

如果时间戳已经过期,则不需要计时器,因此不必返回复杂的结果,而只是返回一个可观察的对象,该对象将仅发出一个true

But if it’s not, lets return that it’s not, and then emit that it is, once it does. We essentially having two observables here, one for the immediate emit, that we made with of and another one that we want to emit after a set amount of time. For this we can use the timer and specify how much it needs to wait. The result of the timer is not important so lets just map the result of that to a true, to signal that it is an expired timestamp.

但是,如果不是,则让它返回不是,然后一旦出现就发出它。 我们基本上有这里有两个观测,一为直接EMIT,我们与制作of ,另外一个我们要在设定的时间量之后放出。 为此,我们可以使用timer并指定需要等待多少时间。 计时器的结果并不重要,因此只需将其结果映射为true即可表示它是过期的时间戳。

Then just combine the two with merge which will create an observable from it’s arguments that will emit the same thing that it’s argument emit.

然后将两者与merge结合在一起,将根据其参数创建一个可观察的对象,该对象将发出与参数发出相同的东西。

Now let’s setup some observables using this function and the different higher order mapper functions that we aim to investigate!

现在,让我们使用此函数以及我们打算研究的其他不同的高阶映射器函数来设置一些可观察对象!

Image for post

A source Subject is there so new values can be supplied to these pipelines.

那里有源Subject ,因此可以将新值提供给这些管道。

Then let’s set up our subscriptions with some extra logging for the time. Here forkJoin creates us an observable that will only emit once all inner observables complete. Start an interval that emits every second (except the first, that’s why startWith is there), and since by default interval emits indefinitely, lets make it complete when others also complete.

然后,让我们设置订阅并添加一些额外的日志记录。 在这里forkJoin为我们创建了一个可观察对象,该观察对象仅在所有内部可观察对象完成后才发出。 启动一个interval ,该interval每秒发出一次(除了第一个interval ,这就是startWith的原因),并且由于默认情况下interval无限期发出的,因此在其他interval也完成时让其完成。

Image for post

Now that all our subscriptions are active, lets feed some values into this pipeline so we can actually see things logged aside from the time ticking.

现在我们所有的订阅都处于活动状态,让我们向该管道中输入一些值,这样我们就可以实际看到除了时间滴答之外还记录了一些内容。

Image for post

A little timeout ensures that logs wont mix up, the first emit happens after a 100 ms, sending a timestamp that will expire in 3 seconds, then a second later we send another that will expire an additional 4 seconds later.

稍有超时可确保日志不会混淆,第一次发出将在100毫秒后发生,发送时间戳记将在3秒后过期,然后第二次发送,另外一个将在4秒后过期。

操场 (Playground)

Let’s see it in action!

让我们看看它的作用!

Open up the console!
打开控制台!

结果 (The results)

Immediately all four emits because all three got that 3 second timestamp, and the inner observable sends immediately that its expired or not.

因为所有三个都获得了3秒的时间戳,所以所有四个立即发出,并且内部可观察对象立即发送其过期或未过期的消息。

time 0 switchMap falsemergeMap falseexhaustMap falseconcatMap false

时间0 switchMap falsemergeMap falseexhaustMap falseconcatMap false

After a second, a new value is added to the subject that will expire at the 5th tick. But only switch and merge emitted. It’s because exhaust doesn’t care about incoming values until the inner observable is finished! And that timer in there is till ticking for another 2 seconds. Concat does care, but it will get back to it once the first inner observable finished.

一秒钟后,会向主题添加一个新值,该值将在第5个滴答处过期。 但是只有切换和合并才会发出。 这是因为直到内部可观察值完成,精疲力竭才关心输入值! 在那里的那个计时器又要滴答滴答地响了2秒钟。 Concat确实会在乎,但是一旦第一个内部可观察的对象完成,它就会恢复原状。

time 1switchMap falsemergeMap false

时间1switchMap falsemergeMap false

At the fourth tick, the first timestamp expires, which means the inner observables emit. But only exhaust and merge emitted! It’s because switchMap completely thrown away the inner observable as soon as the new value came in. Exhaust did not care about the new value, and merge kept both. And concat both emitted the end of the first inner observable, and the start of the second one, because it waited out the end of the first to start with it, concatenating both.

在第四个刻度时,第一个时间戳记到期,这意味着内部可观测对象发出了。 但是只有排气和合并发出! 这是因为 新值一进入, switchMap 完全丢弃了内部可观察到的内容 switchMap不在乎新值,并且合并保留了这两个 和concat都发出了第一个内部可观察对象的末尾和第二个内部可观察对象的开始, 因为它等待第一个内部可观察对象的末尾开始,并同时将两者连接在一起。

time 3mergeMap trueexhaustMap trueconcatMap trueconcatMap false

时间3mergeMap trueexhaustMap trueconcatMap trueconcatMap false

And finally at the sixth tick, the new value expired, switch and merge emitted because only they received the new value, exhaust did not emit the expiration of the second value because it was busy with the previous one. Since the second tick happens at a fixed time and not after a delay, the concat emit is here too. While the first two had a 4 second difference between their last two emits, because of this concat only had 2. If it were a fixed amount of delay, like instead of using a Date for the timer, using a number in milliseconds, the final concat emit would be at tick 7.

最后在第六个滴答处,新值到期,切换和合并发出,因为只有它们接收到新值, 排气没有发出第二个值的到期,因为它忙于前一个值。 由于第二个滴答声发生在固定时间而不是延迟之后,因此concat发出也在这里。 虽然前两个在最后两个发射之间有4秒的差异,但是因为此concat只有2个。如果它是固定的延迟量,例如代替使用Date作为计时器,而是使用毫秒数,则最后一个concat发射将在刻度7处。

time 5switchMap truemergeMap trueconcatMap true

时间5switchMap truemergeMap trueconcatMap true

结论 (Conclusion)

So that’s the long and short of it. switchMap doesn’t care about the inner observable, exhaustMap doesn’t care about the outer observable, mergeMap cares about both immediately and concatMap cares about both but only one at a time, queueing them up.

这就是它的长短。 switchMap不在乎内部的可观察性, exhaustMap不在乎外部的可观察性, mergeMap立即的, concatMap这两者,一次只在一个,将它们排队。

If we need a pipeline which emits if the current value is the expired one at any given time, while it can be replaced at any time, the correct operator is switchMap, so values that are already replaced will not emit that they expired.

如果我们需要一个在当前时间在任何给定时间switchMap过期的值时发出的管道,尽管可以随时替换当前值,但正确的运算符是switchMap ,因此已被替换的值将不会发出它们已过期的信息。

The example code can be found here, you can even just clone that repository, run yarn (npm i -g yarn if you don’t have it installed), open it in VS Code, navigate to that file, and press F5 to run that file in the debugger. Or just use the stackblitz example from earlier.

可以在此处找到示例代码 ,甚至可以克隆该存储库,运行yarn (如果未安装,请运行npm i -g yarn ),在VS Code中将其打开,导航到该文件,然后按F5键运行该文件在调试器中。 或者只是使用前面的stackblitz示例。

翻译自: https://medium.com/swlh/rxjs-and-the-difference-between-mergemap-switchmap-and-exhaustmap-fc23de8c93dc

rxjs mergemap

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值