Próbuję utworzyć operator Rx, który wydaje się całkiem przydatny, ale nieoczekiwanie nie znalazłem żadnych pytań na temat Stackoverflow, które pasują dokładnie. Chciałbym stworzyć odmianę na Throttle
, która natychmiast przepuszcza wartości, jeśli był okres bezczynności. Mój wyimaginowany przypadek użycia jest mniej więcej taki:Niestandardowy operator Rx do dławienia tylko wtedy, gdy pojawiła się ostatnia wartość
Mam menu rozwijane, które uruchamia żądanie sieciowe po zmianie wartości. Jeśli użytkownik przytrzyma klawisz strzałki i szybko przejdzie przez wartości, nie chcę uruchamiać żądania dla każdej wartości. Ale jeśli dławię strumień, to użytkownik musi odczekać czas trwania przepustnicy za każdym razem, gdy tylko wybierają wartość z rozwijanego menu w normalny sposób.
więc podczas normalnego Throttle
wygląda następująco:
Chcę utworzyć ThrottleSubsequent
że wyglądać tak:
Zauważ, że marmury 1, 2 i 6 są przepuszczane przez bezzwłocznie ponieważ każdy z nich przechodzi okres bezczynności.
Moja próba ta wygląda następującą:
public static IObservable<TSource> ThrottleSubsequent<TSource>(this IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
{
// Create a timer that resets with each new source value
var cooldownTimer = source
.Select(x => Observable.Interval(dueTime, scheduler)) // Each source value becomes a new timer
.Switch(); // Switch to the most recent timer
var cooldownWindow = source.Window(() => cooldownTimer);
// Pass along the first value of each cooldown window immediately
var firstAfterCooldown = cooldownWindow.SelectMany(o => o.Take(1));
// Throttle the rest of the values
var throttledRest = cooldownWindow
.SelectMany(o => o.Skip(1))
.Throttle(dueTime, scheduler);
return Observable.Merge(firstAfterCooldown, throttledRest);
}
Ten wydaje do pracy, ale mam to czas trudny rozumowania na ten temat, a mam wrażenie, istnieją pewne przypadki brzegowe tutaj gdzie rzeczy mogą być pomieszane z duplikatami wartości lub czymś. Chciałbym uzyskać informację zwrotną od bardziej doświadczonych Rx-erów, czy ten kod jest poprawny, i/lub czy jest bardziej idiomatyczny sposób na zrobienie tego.
Dzięki za skierowanie mnie do ramy testowej, która wygląda całkiem przydatna. W ThrottleSubsequent2, jakie są wywołania funkcji Publish()? Czy twoja funkcja działa inaczej niż moja w jakiś materialny sposób? – jjoelson
Dodano przykład z efektami ubocznymi subskrypcji, aby pokazać korzyści z publikowania. – Shlomo
Ma sens. Czy można powiedzieć, że powinieneś zawsze używać czegoś takiego jak Publish(), gdy nie wiesz, czy twoja transformacja będzie używana z gorącymi lub zimnymi obserwacjami? – jjoelson