簡體   English   中英

RxJS 節流行為; 立即獲得第一個值

[英]RxJS throttle behavior; get first value immediately

示例 Plunkr: https ://plnkr.co/edit/NZwb3ol8CbZFtSc6Q9zm ? p = preview

我知道 RxJS (5.0 beta.4) 有這 3 種節流方法:

auditTime()throttleTime()auditTime() debounceTime()

我正在尋找的行為是lodash默認情況下在throttle上所做的:

    1. 立即給我第一個值!
    1. 在連續值上,保持給定延遲的值,然后發出最后發生的值
    1. 當油門延遲到期時,返回狀態(1)

理論上這應該是這樣的:

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

但是

  • throttleTime從來沒有給我的最后一個值,如果發射節氣門超時
  • debounceTime不會立即觸發
  • auditTime不會立即觸發

我可以結合任何 RxJS 方法來實現所描述的行為嗎?

對於在 2018 年之后尋找此內容的任何人:這是一年多前添加的內容,但由於某種原因,文檔尚未更新。

RxJS 提交

您可以簡單地將一個配置對象傳遞給throttleTime 默認值為{ leading: true, trailing: false } 要實現此處討論的行為,您只需將trailing設置為true{ leading: true, trailing: true }

編輯:

為了完整起見,這是一個工作片段:

import { asyncScheduler } from 'rxjs'
import { throttleTime } from 'rxjs/operators'

...

observable.pipe(
  throttleTime(100, asyncScheduler, { leading: true, trailing: true })
)

對於較舊的 RxJ,我編寫了一個concatLatest運算符,可以完成您想要的大部分操作。 有了它,您可以使用以下代碼獲得節流行為:

const delay = Rx.Observable.empty().delay(500);
inputObservable
    .map(value => Rx.Observable.of(value).concat(delay))
    .concatLatest()
    .subscribe(...);

這是操作員。 我嘗試更新它以使用 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 中,我重寫了油門/去抖操作符來修復一些邊緣情況的錯誤。 您使用的 4.6.1 仍然存在一些錯誤,但我認為它們不會影響您的測試。

我使用了 auditTime 運算符並更改了 2 行以實現所需的行為。

新 plunker: https ://plnkr.co/edit/4NkXsOeJOSrLUP9WEtp0 ? p = preview

原文:

變化:

來自(審計時間):

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);
  }
}

到(審計時間立即):

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))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM