GoDev

Blog programisty.

Programowanie Reaktywne - Marudzimy - Take.


Artykuł ten jest częścią serii artykułów na temat Programowania reaktywnego.

Zapraszam na GitHub-a.

Tematy

  1. Wstęp
  2. Zabawa z czasem - Timer
  3. Kto za tym stoi? - Scheduler
  4. Nie zapominaj - Subscribe
  5. Zabawa z czasem - Interval
  6. Zabawa z czasem - Buffer
  7. Zabawa z czasem - Delay
  8. Zabawa z czasem - Sample
  9. Zabawa z czasem - Throttle
  10. Zabawa z czasem - Timestamp/TimeInterval
  11. Tworzymy dane - Generators
  12. Tworzymy dane - Własna klasa publikująca
  13. Marudzimy - Skip
  14. Marudzimy - Take
  15. Łap To! - ConsoleKey
  16. Kombinatorzy - Concat
  17. Kombinatorzy - Repeat
  18. Kombinatorzy - Start With
  19. Kombinatorzy - Ambiguous
  20. Kombinatorzy - Merge
  21. Kombinatorzy - Zip
  22. Kombinatorzy - Switch
  23. Kombinatorzy - When-And-Then
  24. Kombinatorzy - Combine Latest
  25. Transformers - Select
  26. Transformers - OfType and Cast
  27. Transformers - Metadata
  28. Bileciki do kontroli - Unit Tests of Interval
  29. Bileciki do kontroli - Unit Tests of Observer Interval
  30. Bileciki do kontroli - Unit Tests of Create Cold/Hot Observable
  31. Szpryca - AutoFac

Wstęp

Reactive Extensions - Skip Krakałem, krakałem o pechu i wykrakałem. Miało być tak szybko z drugim marudą, a tu się pojawiły problemy jakich wcześniej nie przewidziałem. Otóż drugi maruda działa na innej zasadzie. Marudzi ale przy braniu. I tutaj pojawił się problem. Bierzemy pierwsze kilka publikacji na strumień. I kasował swoją subskrypcję, co ciekawe w momencie wyzwalania przez publikację metody OnNext, tym samym dochodziło do jednoczesnego dostępu do tej samej kolekcji przez ForEach i Dispose. Po nierównej walce, obrałem obejście problemu i skorzystałem jedynie ze strumieni generowanych przez Observable.Generator:).

Take - chcę tylko to i to, tamtego już nie…

Tworzymy dwa bardzo podobne do siebie generatory. Po co jest potrzebny ten drugi dowiemy się trochę niżej. Będą one produkować dane co 100ms i 400ms. Kto się zapisze to dostanie;)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void InitializeGenerators()
{
  var initialState = 0;

  _generator1 = Observable.Generate(
    initialState,
    condition => condition < GenerateItemCount,
    iterate => iterate + 1,
    resultSelector => resultSelector,
    timeSelector => TimeSpan.FromMilliseconds(100)
  );

  _generator2 = Observable.Generate(
    initialState,
    condition => condition < GenerateItemCount,
    iterate => iterate + 1,
    resultSelector => resultSelector,
    timeSelector => TimeSpan.FromMilliseconds(400)
  );

I o to nasz pierwszy maruda (TakeLast), dla niego liczy się tylko ten X ostatnich publikowanych na strumień danych. Można by żec, ignorant:). Czeka, czeka, aż pojawi się to co che. Zgarnie swoją wybredną pulę danych.

1
2
3
4
5
6
7
8
private static void AddTakeLastSubscribent()
{
  _generator1
    .TakeLast(10)
    .Subscribe(
      item =>
      {
        Console.WriteLine($"TakeLast 10 items from {GenerateItemCount}: {item}");

Reactive Extensions - Skip

TakeWhile ten ma swoje zasady. Jak strumień ich nie spełnia to nie chce danych. Jest bardzo wybredny. Oczywiście marudy należy wpiąć między strumień a subskrypcję. Jak bardzo wybredny to zależy od nas. Należy pamiętać jednak, że jeżeli choć raz coś mu nie spasuje to się i dan nogę!

1
2
3
4
5
6
7
8
private static void AddTakeWhileSubscribent()
{
  _generator1
    .TakeWhile(x => x < 5)
    .Subscribe(
      item =>
      {
        Console.WriteLine($"TakeWhile, show only some first generated data: {item}");

Szybki Bill (Take), od razu zgarnia dane od dystrybutorów. Jednak wybiera tylko pierwsze sztuki. To wredna bestia jak dostanie co chce, wypisze z subskrypcji 8} i tyle go widzieli…

1
2
3
4
5
6
7
8
private static void AddTakeSubscribent()
{
  _generator1
    .Take(10)
    .Subscribe(
      item =>
      {
        Console.WriteLine($"Take (10): {item}");

Na koniec ostatni i to tutaj właśnie potrzebny jest ten drugi generator (_generator2). Odbiera dane puki _generator1 publikuje. Jeżeli pierwszy padnie. To wówczas TakeUntil już nie chce. I oczywiście wypisze się z listy subskrybentów.

1
2
3
4
5
6
7
8
private static void AddTakeUntilSubscribent()
{
  _generator2
    .TakeUntil(_generator1)
    .Subscribe(
      item =>
      {
        Console.WriteLine($"TakeUntil, generator1 publishing: {item}");

Zakończenie

Dzisiejszy zestaw operatorów, dość podobny do tych z poprzedniego posta. Jedne ignorują drugie biorą. Lustrzane odbicia. Trochę napsuły mi dzisiaj krwi. Walczyłem, walczyłem, a potem zmieniłem taktykę i pokonałem problem. Warto czasem zrobić krok do tyłu by zobaczyć problem z innej perspektywy i rozwiązać go podążając inną drogą. :). Done.


Jest to post wchodzący w skład podjętego wyzwania ogłoszonego przez MIROBURN we vlogu z dnia 3 lutego 2018 roku.

Celem wyzwania jest systematyczne działanie w ciągu 30 dni.

Postanowiłem pisać post dziennie o tematyce Programowania Reaktywnego dla platformy .NET.

Wszelkie źródła związane z postami znajdują się na repozytorium GitHub.

Stan obecny wyzwania: 30 z 30 dni.


Referencje:


Wcześniejszy: Programowanie Reaktywne - Marudzimy - Skip

Następny: Programowanie Reaktywne - Łap To - ConsoleKey