註意:這個速率限制API是在Knockout 3.1.0中添加的。 通常,更改的observable立即通知其訂戶,以便依賴於observable的任何計算的observable或綁定都會同步更新。 但是,rateLimit擴展器會導致observable在指定的時間段內抑制和延遲更改通知。 因此,... ...
註意:這個速率限制API是在Knockout 3.1.0中添加的。
通常,更改的observable立即通知其訂戶,以便依賴於observable的任何計算的observable或綁定都會同步更新。 但是,rateLimit擴展器會導致observable在指定的時間段內抑制和延遲更改通知。 因此,速率限制的observable非同步更新依賴關係。
速率限制擴展器可以應用於任何類型的可觀察量,包括可觀察數組和計算可觀察量。 速率限制的主要用例是:
- 使事情在一定延遲後作出反應
- 將多個更改合併到單個更新中
如果您只需要組合更新而不添加延遲,則延遲更新提供了一種更有效的方法。
應用速率限制擴展
速率限制支持兩種參數格式:
// Shorthand: Specify just a timeout in milliseconds someObservableOrComputed.extend({ rateLimit: 500 }); // Longhand: Specify timeout and/or method someObservableOrComputed.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });
方法選項控制通知何時觸發,並接受以下值:
-
notifyAtFixedRate
— 未另行指定時的預設值。 通知發生在從第一次更改到可觀察者的指定時間段(最初或自上一次通知之後)。 -
notifyWhenChangesStop
— 通知發生在可觀察者在指定時間段內沒有發生變化之後。 每次可觀察到的變化,該定時器被重置,因此如果可觀察者連續地改變比超時期間更頻繁,則不能發生通知。
示例1:基礎示例
考慮下麵代碼中的observable:
var name = ko.observable('Bert'); var upperCaseName = ko.computed(function() { return name().toUpperCase(); });
通常,如果您更改名稱如下:
name('The New Bert');
upperCase Name將在下一行代碼運行之前立即完成。 但是如果你改為使用rateLimit定義名稱如下:
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時:
- 對可觀測量的寫入不被延遲; observables值立即更新。 對於可寫的計算可觀測量,這意味著寫函數總是立即運行。
- 所有更改通知都會延遲,包括手動調用valueHasMutated時。 這意味著您不能使用valueHasMutated強制速率限制的observable通知未更改的值。
- 預設速率限制方法與throttle演算法不同。 要匹配throttle行為,請使用notifyWhenChangesStop方法。
- 速率限制的計算觀察值的評估不受速率限制; 如果你讀它的值,它會重新評估。