De .Net Reactive Extension biedt ontwikkelaars een set functies om een reactief programmeermodel te implementeren voor .Net-ontwikkelaars, zodat het afhandelen van gebeurtenissen eenvoudiger en expressiever wordt met behulp van declaratieve acties. Hoewel de belangrijkste hoekstenen van reactieve schaalverdeling de IObserver en IObservable interfaces zijn, hoef je als ontwikkelaar deze interfaces vaak niet zelf te implementeren. De bibliotheek ondersteunt het ingebouwde type Subject<T>, dat interfaces implementeert en veel functies ondersteunt.
Thema's vormen de basis voor de verschillende onderwerpen die in de bibliotheek beschikbaar zijn, en er zijn andere thema's - ReplaySubject<T>, BehaviorSubject<T> en AsyncSubject<T>. Het is nuttig om de essentiële verschillen tussen deze te begrijpen en hoe je ze kunt gebruiken om de bibliotheek beter te benutten.
In dit artikel vergelijken we Subject<T> en zijn broer of zus, en proberen we de verschillen in hun gedrag te illustreren.
Onderwerp<T>
Zoals eerder vermeld,<T> vormt Subject de basis voor de beschikbare thema's, waardoor het een gemakkelijke manier biedt om de bibliotheek te gebruiken zonder zelf de IObservable<T> en IObserver-interfaces te hoeven<T> implementeren. Hieronder wordt een eenvoudige demonstratie van het thematype getoond.
In de bovenstaande code hebben we een <T>instantie van Subject gemaakt, en omdat deze<T> IObserver en IObserverable <T>implementeert, gebruiken we dezelfde instantie om de waarde te abonneren en te publiceren naar IObserver. Een ander belangrijk punt om hier op te merken is hoe we de overload van de Subscribe-methode gebruiken om acties als input te accepteren. Dit gebeurt voor elke gepubliceerde waarde, waarbij het nummer in dit geval naar de console wordt geprint.
Laten we proberen de gepubliceerde waarden en de waarden die IObserver (in deze actie<T>) afdrukt aan de console te tonen in de volgende afbeelding. Dit helpt ons om de overgebleven broers en zussen en varianten gemakkelijk te vergelijken.
De eerste regel vertegenwoordigt de gepubliceerde waarde, en de tweede regel de waarde die door de IObserver is ontvangen. Daarnaast hebben we een regel toegevoegd om aan te geven op welk punt de waarnemer zich tijdens de uitvoering op de stream abonneert. Deze lijn wordt weergegeven door een verticale stippellijn.
In de bovenstaande code zagen we dat de waarnemer zich op de datastream had geabonneerd voordat hij de eerste waarde publiceerde. De afbeelding toont de Subscriber-lijn vóór het eerste element. Zoals je kunt zien aan de uitgangslijn, heeft dit geen effect op de uitgang (op dit punt).
Maar wat als de waarnemer pas op de data inschrijft nadat sommige waarden al zijn gepubliceerd? Heeft dit invloed op de gegevens die door waarnemers worden ontvangen? Voordat we naar de output kijken, schrijven we eerst dezelfde code.
In bovenstaande code kunnen we zien dat de waarnemer pas op de datastream inschrijft nadat twee waarden (1 en 2) zijn gepubliceerd. Zoals te verwachten is, zal dit ertoe leiden dat waarnemers geen gepubliceerde gegevens ontvangen voordat ze de abonnementsmethode oproepen. Zoals te zien is in de onderstaande figuur.
Wat als je alle gepubliceerde waarden wilt lezen, zelfs als de waarnemer laat abonneert? Hier komt ReplaySubject<T> om de hoek kijken.
HerhalingOnderwerp<T>
ReplaySubject<T> cachet waarden en speelt ze opnieuw af voor latere abonnees. Dit is handig om raceomstandigheden te vermijden. Laten we de vorige code veranderen naar ReplaySubject<T> en kijken hoe dit beïnvloedt wat de waarnemer ontvangt.
Zoals te zien is in de bovenstaande code, is er<T> <T>nauwelijks enige verandering in de code, behalve dat we nu ReplaySubject gebruiken in plaats van subject. Het volgende diagram illustreert de impact op de gegevens die de waarnemer ontvangt.
Zoals te zien is op de afbeelding, wordt de gecachte waarde nu opnieuw afgespeeld aan de abonnee, zelfs als de abonnee zich later abonneert. Natuurlijk heeft deze nuttige functie een prijs. Deze implementatie zal elke waarde die door de abonnee wordt gepubliceerd cachen, wat problemen met het geheugen kan veroorzaken wanneer de hoeveelheid data aanzienlijk groter is.
ReplaySubject<T> heeft echter meer dan één manier om dit probleem op te lossen. Voor dit voorbeeld bekijken we twee voorbeelden die grootte- en tijdsbeperkingen gebruiken om de gecachte waarde te beperken.
In het eerste geval gebruiken we de grootte van de cache om de waarde van de cache te beperken. <T>De constructor van ReplaySubject levert een overload, die een geheel getal accepteert dat de grootte van de cachebuffer (maximale aantal elementen) weergeeft. In ons voorbeeld veranderen we de code om de cachegrootte te beperken tot 1.
Let op hoe we <T>de constructor overload van ReplaySubject gebruiken om de grootte van de cache als 1 te geven. Dit beperkt caching en zorgt ervoor dat slechts één element wordt gecachet en direct na publicatie wordt vervangen door een nieuw element. De impact van de wijziging wordt hieronder getoond.
Een andere manier om caching te beperken is door de tijd van het gecachte item te beperken, of met andere woorden, een vervaldatum voor het gecachte item te geven.
Laten we code schrijven om dat voorbeeld te illustreren.
Net als bij de vorige code gebruiken we<T> de overload van de ReplaySubject-constructor om de vervaldatum van items in de cache aan te geven. Om ons standpunt te illustreren, introduceerden we een vertraging tussen het vrijgeven van de waarden.
Omdat het een volle 1200ms duurt voordat de waarnemer zich aanmeldt, worden alle elementen die de 1000ms vervaldatum overschrijden uit de cache verwijderd. In dit voorbeeld wordt waarde 1 uit de cache verwijderd en wordt deze niet opnieuw afgespeeld aan late abonnees. Zoals te zien is in de onderstaande figuur.
Er <T>zijn andere overloads voor ReplaySubject die meer flexibiliteit bieden en de gecachte waarden fijn afstemmen, maar voor voorbeelden houden we de twee hierboven al besproken voorbeelden aan.
GedragOnderwerp<T>
BehaviourSubject <T>lijkt erg op ReplaySubject<T> in die zin dat het helpt om waarden te cachen. Maar er is een aanzienlijk verschil. BehaviourSubject<T> cachet alleen de laatst gepubliceerde waarde. Voordat we hier verder op ingaan, laten we wat code schrijven.
Als de BehaviorSubject<T> slechts één waarde cachet (die laatst bekend is), hoe verschilt dat dan van een ReplaySubject van grootte 1<T>? Het volgende diagram geeft duidelijk de situatie van de bovenstaande code weer.
Dit is echter niet helemaal waar. Er zijn hier twee belangrijke verschillen om te begrijpen. De eerste is de aanwezigheid van defaults. Let op dat we in de bovenstaande code <T>de waarde 0 als standaard geven in de constructor van BehaviourSubject. Als er geen waarde in de cache bestaat (of met andere woorden, er is geen data gepubliceerd voordat de waarnemer zich aanmeldde), wordt de standaardwaarde teruggegeven. Dit is anders dan ReplaySubject, dat een grootte van 1 heeft<T>, maar geen waarde heeft. De volgende code en een visuele weergave van de sequentie tonen dit gedrag aan.
Het tweede verschil is hoe BehaviorSubject<T> en ReplaySubject<T> zich gedragen bij het abonneren op een voltooide sequentie. Wanneer je je na voltooiing abonneert, heeft BehaviorSubject <T> geen waarde, zoals te zien is in de onderstaande code.
Abonnees krijgen gegarandeerd geen waarde omdat abonnementen pas na voltooiing plaatsvinden.
Dit <T>is echter het geval bij ReplaySubject. Er is geen garantie dat de waarnemer geen waarden zal ontvangen, zoals weergegeven in de onderstaande code.
Zoals in de bovenstaande code te zien is, is de cache 1 groot en zelfs als het abonnement wordt aangeroepen nadat de oproep is voltooid, blijft de cache (totdat aan de vervalvoorwaarden is voldaan), dus in dit geval wordt de laatst gepubliceerde waarde ontvangen.
AsyncSubject<T>
AsyncSubject <T>is de laatste broer of zus van de Subject die we in dit artikel zullen behandelen<T>, en het lijkt sterk op de vorige twee (ReplaySubject en BehaviourSubject) doordat het ook resultaten cachet. Maar er is ook een aanzienlijk verschil. AsyncSubject publiceert de laatst gecachte waarde alleen als de reeks als voltooid is gemarkeerd <T> (het cachet slechts één waarde, de laatste waarde).
Overweeg de volgende code.
Dit genereert een waarde voor de waarnemer waarbij de reeks wordt gemarkeerd als de laatste waarde die vóór voltooiing is gepubliceerd - waarde 4. Zoals te zien is in de onderstaande figuur.
Maar wat gebeurt er als we de oproep overslaan die de sequentie als voltooid markeert? Laten we de regel uitsteken, en het opnieuw proberen.
Dit genereert geen gegevens voor de waarnemer omdat AsyncSubject<T> resultaten pas publiceert nadat de sequentie als voltooid is gemarkeerd.
Dit is een belangrijk verschil waar iedereen die AsyncSubject gebruikt <T>in gedachten moet houden.
conclusie
Dit artikel toont <T>de verschillen tussen de verschillende broers en zussen van Subject en enkele van zijn varianten. Het is vaak nuttig om je bewust te zijn van deze subtiele verschillen, omdat ze anders gedrag kunnen vertonen dan je verwachtte als je het niet doorhebt.
Originele link:De hyperlink-login is zichtbaar.
|