Использование Rx для выполнения отложенного действия с отменой - PullRequest
1 голос
/ 03 апреля 2012

У кого-нибудь есть пример кода Rx, который показывает, как выполнить действие из-за отложенного события, которое отменено другим событием? Например, отображение всплывающей подсказки при наведении курсора на кнопку в течение определенного периода времени?

Действие "отображение всплывающей подсказки"

Продолжительность - это "определенный период времени"

И событие отмены будет «мышью вне», если мышь перестанет зависать над кнопкой.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 04 апреля 2012

Всегда начинайте с разбивки проблемы на то, что у вас есть и что вы хотите, превратите это в сигнатуру функции и посмотрите, обнаружит ли это реализацию.

выполнить действие из-за задержкисобытие, которое отменяется другим событием

, поэтому у вас есть источник запуска, длительность задержки и источник отмены

Желаемое поведение, которое вы описываете:

  • Для каждого источника триггера
  • Задержка на указанное время
  • Если в течение этого времени отмена не происходит, выведите исходное значение

Теперь, когда у нас естьНапример, мы можем сделать подпись и рассмотреть реализацию

??? DelayOrCancel<???>(this IObservable<T> source, 
                       TimeSpan delay, 
                       IObservable<TCancel> cancel);

В зависимости от природы источника отмены, вам может понадобиться передать Func<T, IObservable<TCancel>>, но, похоже, это будет работать в вашем случае.

Первые две строки спецификации предполагают SelectMany (каждый элемент в источнике делает другую наблюдаемую, которая будет объединена обратно в одну наблюдаемую).Чтобы получить отмену, нам просто нужно дождаться задержки или до отмены, что мы можем сделать с TakeUntil.Поскольку конечными элементами будут исходные элементы, тип возврата будет таким же, как и исходный.

IObservable<T> DelayOrCancel<T, TCancel>(this IObservable<T> source, 
                                         TimeSpan delay, 
                                         IObservable<TCancel> cancel)
{
    //argument checking skipped
    return from s in source
           from i in Observable.Timer(delay).TakeUntil(cancel)
           select s;
}
0 голосов
/ 04 апреля 2012
IObservable<Unit> startStream;
IObservable<Unit> cancelStream;
TimeSpan delay;

var filtered = Observable
  .Merge(start.Select(_=>true), cancel.Select(_=>false)
  .Throttle(delay)
  .Where(b=>b)
  .Do(_=> ...)
  .Subscribe();

Если ваши события запуска и отмены не являются наблюдаемыми, вам необходимо преобразовать их, используя Observable.FromEventPattern .

...