2016-05-10 3 views
4

Пример Plunkr: https://plnkr.co/edit/NZwb3ol8CbZFtSc6Q9zm?p=previewRxJS поведение дроссельной заслонки; получить первое значение сразу

Я понимаю, что есть эти 3 метода дроссельной заслонки для rxjs (5,0 beta.4):

auditTime(), throttleTime() и debounceTime()

поведение Я ищет только один lodash по умолчанию на дроссельной заслонке:

  • 1) Немедленно дайте мне первое значение!
  • 2) на последовательных значениях, удерживая значения для данной задержки, а затем испускают последнее происходившее значение
  • 3), когда задержка дроссельной истекла, вернуться в состояние (1)

В теории это должно выглядеть следующим образом:

inputObservable 
    .do(() => cancelPreviousRequest()) 
    .throttleTime(500) 
    .subscribe((value) => doNextRequest(value)) 

Но

  • throttleTime никогда не дает мне последнее значение, если излучаемый в Тайм-аут дроссельной
  • debounceTime не срабатывает сразу
  • auditTime не срабатывает сразу

Могу ли я комбинировать любой из методов rxjs для достижения описанного поведения?

ответ

1

Я взял оператор auditTime и сменил 2 строки для достижения желаемого поведения.

Новый plunker: https://plnkr.co/edit/4NkXsOeJOSrLUP9WEtp0?p=preview

Оригинал:

Изменения:

из (auditTime):

protected _next(value: T): void { 
    this.value = value; 
    this.hasValue = true; 
    if (!this.throttled) { 
    this.add(this.throttled = this.scheduler.schedule(dispatchNext, this.duration, this)); 
    } 
} 

clearThrottle(): void { 
    const { value, hasValue, throttled } = this; 
    if (throttled) { 
    this.remove(throttled); 
    this.throttled = null; 
    throttled.unsubscribe(); 
    } 
    if (hasValue) { 
    this.value = null; 
    this.hasValue = false; 
    this.destination.next(value); 
    } 
} 

к (auditTimeImmediate):

protected _next(value: T): void { 
    this.value = value; 
    this.hasValue = true; 
    if (!this.throttled) { 
     // change 1: 
     this.clearThrottle(); 
    } 
} 

clearThrottle(): void { 
    const { value, hasValue, throttled } = this; 
    if (throttled) { 
     this.remove(throttled); 
     this.throttled = null; 
     throttled.unsubscribe(); 
    } 
    if (hasValue) { 
     this.value = null; 
     this.hasValue = false; 
     this.destination.next(value); 
     // change 2: 
     this.add(this.throttled = this.scheduler.schedule(dispatchNext, this.duration, this)); 
    } 
} 

Так я начала тайм-аут после того, как значение было next-е изд.

Использование:

inputObservable 
    .do(() => cancelPreviousRequest()) 
    .auditTimeImmediate(500) 
    .subscribe((value) => doNextRequest(value)) 
3

Для старых RxJs я написал оператор concatLatest, который делает большую часть того, что вы хотите. С его помощью вы можете получить свое дросселирование с помощью этого кода:

Вот оператор. Я принял удар на его обновления для работы с RxJS5:

Rx.Observable.prototype.concatLatest = function() { 
    /// <summary> 
    /// Concatenates an observable sequence of observable sequences, skipping sequences that arrive while the current sequence is being observed. 
    /// If N new observables arrive while the current observable is being observed, the first N-1 new observables will be thrown 
    /// away and only the Nth will be observed. 
    /// </summary> 
    /// <returns type="Rx.Observable"></returns> 
    var source = this; 

    return Rx.Observable.create(function (observer) { 
     var latest, 
      isStopped, 
      isBusy, 
      outerSubscription, 
      innerSubscription, 
      subscriptions = new Rx.Subscription(function() { 
       if (outerSubscription) { 
       outerSubscription.unsubscribe(); 
       } 
       if (innerSubscription) { 
       innerSubscription.unsubscribe(); 
       } 
      }), 
      onError = observer.error.bind(observer), 
      onNext = observer.next.bind(observer), 
      innerOnComplete = function() { 
       var inner = latest; 
       if (inner) { 
        latest = undefined; 
        if (innerSubscription) { 
         innerSubscription.unsubscribe(); 
        } 
        innerSubscription = inner.subscribe(onNext, onError, innerOnComplete); 
       } 
       else { 
        isBusy = false; 
        if (isStopped) { 
         observer.complete(); 
        } 
       } 
      }; 

     outerSubscription = source.subscribe(function (newInner) { 
      if (isBusy) { 
       latest = newInner; 
      } 
      else { 
       isBusy = true; 
       if (innerSubscription) { 
        innerSubscription.unsubscribe(); 
       } 
       innerSubscription = newInner.subscribe(onNext, onError, innerOnComplete); 
      } 
     }, onError, function() { 
      isStopped = true; 
      if (!isBusy) { 
       observer.complete(); 
      } 
     }); 

     return subscriptions; 
    }); 
}; 

И вот обновленный plunkr: https://plnkr.co/edit/DSVmSPRijJwj9msefjRi?p=preview

Примечание Я обновил версию lodash до последней версии. В lodash 4.7 я переписал операторы дроссельной заслонки/debounce, чтобы исправить некоторые ошибки в кромке. Вы использовали 4.6.1, в котором все еще были некоторые из этих ошибок, хотя я не думаю, что они влияют на ваш тест.

+0

Привет @Brandon, большой ответ. Можете ли вы предоставить ссылку на plunkr с помощью оператора concatLatest, используя RxJS 4.x? (Я бы не спросил, так как вопрос специфичен для RxJS 5, но вы сказали, что у вас уже было это удобно :) – HipsterZipster

+0

@HipsterZipster Я написал эту версию для RxJS 2. Я предполагаю, что она будет работать и в 4: https: // gist.github.com/bman654/92749cd93cdd84a540e41403f25a2105 – Brandon

Смежные вопросы