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. 速率限制的计算观察值的评估不受速率限制; 若是你读它的值,它会从新评估。
相关文章
相关标签/搜索