KnockoutJS 3.X API 第七章 其餘技術(4) 速率限制

注意:這個速率限制API是在Knockout 3.1.0中添加的。

一般,更改的observable當即通知其訂戶,以便依賴於observable的任何計算的observable或綁定都會同步更新。 可是,rateLimit擴展器會致使observable在指定的時間段內抑制和延遲更改通知。 所以,速率限制的observable異步更新依賴關係。 算法

速率限制擴展器能夠應用於任何類型的可觀察量,包括可觀察數組和計算可觀察量。 速率限制的主要用例是: 數組

  • 使事情在必定延遲後做出反應
  • 將多個更改合併到單個更新中

若是您只須要組合更新而不添加延遲,則延遲更新提供了一種更有效的方法。 app

應用速率限制擴展

速率限制支持兩種參數格式:異步

// Shorthand: Specify just a timeout in milliseconds
someObservableOrComputed.extend({ rateLimit: 500 });
 
// Longhand: Specify timeout and/or method
someObservableOrComputed.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });

方法選項控制通知什麼時候觸發,並接受如下值: 函數

  1. notifyAtFixedRate — 未另行指定時的默認值。 通知發生在從第一次更改到可觀察者的指定時間段(最初或自上一次通知以後)。this

  2. notifyWhenChangesStop — 通知發生在可觀察者在指定時間段內沒有發生變化以後。 每次可觀察到的變化,該定時器被重置,所以若是可觀察者連續地改變比超時期間更頻繁,則不能發生通知。spa

示例1:基礎示例

考慮下面代碼中的observable:code

var name = ko.observable('Bert');
 
var upperCaseName = ko.computed(function() {
    return name().toUpperCase();
});

一般,若是您更更名稱以下:blog

name('The New Bert');

upperCase Name將在下一行代碼運行以前當即完成。 可是若是你改成使用rateLimit定義名稱以下:ci

var name = ko.observable('Bert').extend({ rateLimit: 500 });

upperCaseName不會在名稱更改時當即從新計算,而是在將其新值通知給upperCaseName以前,將等待500毫秒(半秒),而後從新計算其值。 不管在這500ms內名稱是多少次更改,upperCaseName只會更新一次最新的值。

示例2:當用戶中止輸入時執行某些操做

在這個實例中,有一個instantValue observable,當你按下一個鍵時當即反應。 而後將其封裝在delayedValue計算observable中,該observable配置爲僅當更改中止至少400毫秒時通知使用notifyWhenChangesStop rate-limit方法。

嘗試一下:

Type stuff here:

Current delayed value:

Stuff you have typed:

UI源碼:

<p>Type stuff here: <input data-bind='textInput: instantaneousValue' /></p>
<p>Current delayed value: <b data-bind='text: delayedValue'> </b></p>
 
<div data-bind="visible: loggedValues().length > 0">
    <h3>Stuff you have typed:</h3>
    <ul data-bind="foreach: loggedValues">
        <li data-bind="text: $data"></li>
    </ul>
</div>

視圖模型源碼:

function AppViewModel() {
    this.instantaneousValue = ko.observable();
    this.delayedValue = ko.pureComputed(this.instantaneousValue)
        .extend({ rateLimit: { method: "notifyWhenChangesStop", timeout: 400 } });
 
    // Keep a log of the throttled values
    this.loggedValues = ko.observableArray([]);
    this.delayedValue.subscribe(function (val) {
        if (val !== '')
            this.loggedValues.push(val);
    }, this);
}
 
ko.applyBindings(new AppViewModel());

計算可觀測量的特殊考慮

對於計算的observable,當計算的observable的依賴性之一改變而不是其值改變時,觸發速率限制定時器。 計算的observable不會從新求值,直到實際須要它的值 - 在發生更改通知的超時時間段以後,或直接訪問計算的可觀察值時。 若是須要訪問計算的最近評估的值,可使用peek方法執行此操做。

強制限速觀察者老是通知訂閱者

當any observable的值是原始值(數字,字符串,布爾值或null)時,只有當observable的依賴項設置爲實際上與以前不一樣的值時,纔會通知它的依賴項。 所以,原始值的速率限制可觀察量只有當它們的值在超時週期結束時實際上不一樣時才通知。 換句話說,若是原始值的速率限制的observable被改變爲新的值,而後在超時時間段結束以前改變回原始值,則不會發生通知。

若是要確保始終通知訂閱者更新,即便該值相同,除了rateLimit以外,還要使用notify擴展器:

myViewModel.fullName = ko.computed(function() {
    return myViewModel.firstName() + " " + myViewModel.lastName();
}).extend({ notify: 'always', rateLimit: 500 });

與延遲更新的比較

Knockout 3.4.0版本增長了對延遲更新的支持,經過使通知和更新異步,它的工做方式相似於速率限制。 可是,不是使用定時延遲,而是在執行I / O,迴流或重繪以後,在當前任務以後儘快處理延遲更新。 若是要升級到3.4.0而且使用速率限制超時(例如,0毫秒)的代碼,則能夠修改成使用延遲更新:

ko.computed(function() {
    // ....
}).extend({ deferred: true });

 

與throttle延長器比較

若是要使用已棄用的throttle擴展程序遷移代碼,則應注意如下方法,即rateLimit擴展程序與throttle擴展程序不一樣。

使用rateLimit時:

  1. 對可觀測量的寫入不被延遲; observables值當即更新。 對於可寫的計算可觀測量,這意味着寫函數老是當即運行。
  2. 全部更改通知都會延遲,包括手動調用valueHasMutated時。 這意味着您不能使用valueHasMutated強制速率限制的observable通知未更改的值。
  3. 默認速率限制方法與throttle算法不一樣。 要匹配throttle行爲,請使用notifyWhenChangesStop方法。
  4. 速率限制的計算觀察值的評估不受速率限制; 若是你讀它的值,它會從新評估。
相關文章
相關標籤/搜索