This article is a mirror article of machine translation, please click here to jump to the original article.

View: 2585|Reply: 2

[Source] Explore topics in the .Net Reactive Responsive Extension

[Copy link]
Posted on 1/27/2024 12:17:19 PM | | | |
The .Net Reactive Extension provides developers with a set of features to implement a reactive programming model for .Net developers to make event handling simpler and more expressive using declarative actions. While the key cornerstones of reactive scaling are the IObserver and IObservable interfaces, as a developer, you often don't need to implement these interfaces yourself. The library supports the built-in type Subject<T>, which implements interfaces and supports many functions.

Themes are the basis for the different topics available in the library, and there are other themes - ReplaySubject<T>, BehaviorSubject,<T> and AsyncSubject<T>. It's useful to understand the essential differences between them and how to use them to make better use of the library.

In this article, we will compare Subject<T> and its sibling, trying to illustrate the differences between their behavior.

Subject<T>

As mentioned earlier, Subject<T> is the basis for the available themes, providing an easy way to use the library without having to implement the IObservable<T> and IObserver<T> interfaces yourself. A simple demonstration of the theme type is shown below.

In the code above, we created an <T>instance of Subject, and since it implements<T> IObserver and IObserverable<T>, use the same instance to subscribe and publish the value to IObserver. Another important point to note here is how we use the overload of the Subscribe method to accept actions as input. This will be done for each published value, in this case printing the number to the console.

Let's try to show the published values and the values that IObserver (in this Action<T>) prints to the console in the following image. This will help us easily compare the remaining siblings and variants.



The first line represents the published value, and the second line represents the value received by the IObserver. In addition, we have added a line to indicate at what point the observer subscribes to the stream during execution. This line is represented by a vertical dotted line.

In the code above, we noticed that the observer subscribed to the datastream before publishing the first value. The image shows the Subscriber line placed before the first element. As you can see from the output line, this has no effect on the output (at this point).

But what if the observer only subscribes to the data after some values have already been published? Does this have an impact on the data received by observers? Before looking at the output, let's write the same code first.

In the above code, we can observe that the observer subscribes to the datastream only after two values (1 and 2) are published. As one might expect, this will cause observers to not receive data published before calling the subscription method. As shown in the figure below.



What if you want to read all published values, even if the observer subscribes late? This is where ReplaySubject<T> comes into play.

ReplaySubject<T>

ReplaySubject<T> caches values and replays them for later subscribers. This is useful for avoiding race conditions. Let's change the previous code to use ReplaySubject<T> and see how it affects what the observer receives.

As shown in the code above, there is<T> <T>hardly any change in the code except that we now use ReplaySubject instead of subject. The following diagram illustrates the impact on the data received by the observer.



As shown in the image, the cached value is now replayed to the subscriber even if the subscriber subscribes later. Of course, this useful feature comes at a price. This implementation will cache every value published by the subscriber, which can cause bad memory issues when the amount of data is significantly larger.

However, ReplaySubject<T> has more than one way to solve this problem. For the sake of this example, we'll look at two examples that will use size and time constraints to limit the cached value.

As the first case, we will use the size of the cache to limit the value of the cache. <T>ReplaySubject's constructor provides an overload, which accepts an integer that represents the size of the cache buffer (maximum element count). In our example, let's change the code to limit the cache size to 1.

Note how we use <T>ReplaySubject's constructor overload to provide the size of the Cache as 1. This limits caching and ensures that only one element is cached and replaced with a new element as soon as it is published. The impact of the change is shown below.



Another way to limit caching is to limit the time of the cached item, or in other words, to provide an expiration time for the cached item.

Let's write code to illustrate that example.

Similar to the previous code, we use<T> the overload of the ReplaySubject constructor to specify the expiration time of items in the cache. To demonstrate our case, we introduced a delay between the release of values.

Since it takes a full 1200ms before the observer subscribes, any elements that exceed the 1000ms expiration time will be removed from the cache. In this example, this will cause value 1 to be removed from the cache and will not be replayed to late subscribers. As shown in the figure below.



There <T>are other overloads for ReplaySubject that provide more flexibility and fine-tune the cached values, but for examples, we'll keep the two examples already covered above.

BehaviourSubject<T>

BehaviourSubject <T>is very similar to ReplaySubject<T> in that it helps cache values. But there is a significant difference. BehaviourSubject<T> caches only the last published value. Before we get into this further, let's write some code.

If the BehaviorSubject<T> only caches a single value (which is last known), how is it different from a ReplaySubject of size 1<T>? The following diagram clearly reflects the situation of the code above.



However, this is not entirely true. There are two important differences to understand here. The first is the presence of defaults. Note that in the code above, we <T>provide the value 0 as the default in the constructor of BehaviourSubject. If no value exists in the cache (or in other words, no data was published before the observer subscribed), the default value will be returned. This is different from ReplaySubject, which has a size of 1<T>, which doesn't have any value. The following code and a visual representation of the sequence demonstrates this behavior.



The second difference is how BehaviorSubject<T> and ReplaySubject<T> behave when subscribing to a completed sequence. When you subscribe after completion, the BehaviorSubject <T> will have no value, as shown in the code below.

Subscribers are guaranteed not to receive any value because subscriptions occur after completion.



However, <T>this is the case with ReplaySubject . There is no guarantee that the observer will not receive any values, as shown in the code below.

As shown in the code above, the cache is 1 in size and even if the subscription is called after the call is completed, the cache will remain (until the expiration condition is met), so in this case the last published value will be received.



AsyncSubject<T>

AsyncSubject <T>is the last sibling of the Subject that we will explore in this article<T>, and it is very similar to the previous two (ReplaySubject and BehaviourSubject) in that it also caches results. But again there is a significant difference. AsyncSubject publishes the last cached value only if the sequence is marked as complete <T> (it caches only one value, the last value).

Consider the following code.

This will generate a value for the observer that the sequence is marked as the last value published before completion - value 4. As shown in the figure below.



But what happens if we skip the call that marks the sequence as complete? Let's comment out the line and try again.

This does not generate any data for the observer because AsyncSubject<T> publishes results only after the sequence is marked as complete.



This is a significant difference that anyone using AsyncSubject <T>should keep in mind.

conclusion

This article demonstrates <T>the differences between the various siblings of Subject and some of its variations. It's often useful to be aware of these subtle differences, as they may exhibit different behavior than you expected if you don't realize it.

Original link:The hyperlink login is visible.





Previous:.NET/C# checks if a TCP port is available
Next:NSIS (1) Make a simple installer
 Landlord| Posted on 1/27/2024 12:19:47 PM |
Subject topic subscription for Angular RxJS
https://www.itsvse.com/thread-9209-1-1.html
 Landlord| Posted on 4/28/2024 11:36:59 AM |
ASP.NET Core uses the MediatR intermediary model
https://www.itsvse.com/thread-9272-1-1.html
Disclaimer:
All software, programming materials or articles published by Code Farmer Network are only for learning and research purposes; The above content shall not be used for commercial or illegal purposes, otherwise, users shall bear all consequences. The information on this site comes from the Internet, and copyright disputes have nothing to do with this site. You must completely delete the above content from your computer within 24 hours of downloading. If you like the program, please support genuine software, purchase registration, and get better genuine services. If there is any infringement, please contact us by email.

Mail To:help@itsvse.com