注意:这个速率限制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" } });

方法选项控制通知何时触发,并接受以下值:

  1. notifyAtFixedRate — 未另行指定时的默认值。 通知发生在从第一次更改到可观察者的指定时间段(最初或自上一次通知之后)。

  2. 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时:

  1. 对可观测量的写入不被延迟; observables值立即更新。 对于可写的计算可观测量,这意味着写函数总是立即运行。

  2. 所有更改通知都会延迟,包括手动调用valueHasMutated时。 这意味着您不能使用valueHasMutated强制速率限制的observable通知未更改的值。
  3. 默认速率限制方法与throttle算法不同。 要匹配throttle行为,请使用notifyWhenChangesStop方法。
  4. 速率限制的计算观察值的评估不受速率限制; 如果你读它的值,它会重新评估。

KnockoutJS 3.X API 第七章 其他技术(4) 速率限制的更多相关文章

  1. KnockoutJS 3.X API 第七章 其他技术(8) 异步错误处理

    注意:本文档适用于Knockout 3.4.0及更高版本. ko.onError Knockout包装内部异步调用,并在抛出原始错误之前查找可选的ko.onError回调以执行(如果遇到异常). 这使 ...

  2. KnockoutJS 3.X API 第七章 其他技术(7) 微任务

    注意:本文档适用于Knockout 3.4.0及更高版本. Knockout的微任务队列 Knockout的微任务队列支持调度任务尽可能快地运行,同时仍然是异步的,努力安排它们在发生I / O,回流或 ...

  3. KnockoutJS 3.X API 第七章 其他技术(6) 使用“fn”添加自定义函数

    有时,您可能会通过向Knockout的核心值类型添加新功能来寻找机会来简化您的代码. 您可以在以下任何类型中定义自定义函数: 因为继承,如果你附加一个函数到ko.subscribable,它将可用于所 ...

  4. KnockoutJS 3.X API 第七章 其他技术(5) 使用其他事件处理程序

    在大多数情况下,数据绑定属性提供了一种干净和简洁的方式来绑定到视图模型. 然而,事件处理是一个常常会导致详细数据绑定属性的领域,因为匿名函数通常是传递参数的推荐技术. 例如: <a href=& ...

  5. KnockoutJS 3.X API 第七章 其他技术(3) 延迟更新

    .example { display: inline-block; padding: 1em; margin-right: 2em; background: #F6F6EF; } 注意:本文档适用于K ...

  6. KnockoutJS 3.X API 第七章 其他技术(2) 使用扩展器来增加可观察量(监控属性)

    Knockout observables提供了支持读取/写入值并在值改变时通知订阅者所需的基本功能. 但在某些情况下,您可能希望向可观察者添加其他功能. 这可能包括通过在可观察者前面放置一个可写的计算 ...

  7. KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据

    Knockout允许您实现复杂的客户端交互性,但几乎所有Web应用程序还需要与服务器交换数据,或至少将本地存储的数据序列化. 最方便的交换或存储数据的方式是JSON格式 - 大多数Ajax应用程序今天 ...

  8. KnockoutJS 3.X API 第六章 组件(5) 高级应用组件加载器

    无论何时使用组件绑定或自定义元素注入组件,Knockout都将使用一个或多个组件装载器获取该组件的模板和视图模型. 组件加载器的任务是异步提供任何给定组件名称的模板/视图模型对. 本节目录 默认组件加 ...

  9. KnockoutJS 3.X API 第六章 组件(3) 组件绑定

    组件绑定将指定的组件注入到元素中,并且可选地将参数传递给它. 本节目录 一个例子 API 组件生命周期 备注1:仅限模板组件 备注2:使用没有容器元素的组件 备注3:将标记传递给组件 处置和内存管理 ...

随机推荐

  1. java常用设计模式

    一个程序员对设计模式的理解: "不懂"为什么要把很简单的东西搞得那么复杂. 后来随着软件开发经验的增加才开始明白我所看到的"复杂"恰恰就是设计模式的精髓所在,我 ...

  2. .NET string字符串的截取、移除、替换、插入

    在实际开发中经常要用到string的各种截取等操作,在这里总结自己认为经常出现的.NET 字符串的截取.移除.替换.插入操作,方面以后查阅. 前台代码: <%@ Page Language=&q ...

  3. maven构建简单的web项目

    把jdk给换掉 项目修改好了以后写个页面测试一下,结果正常 下面应该添加依赖让web项目一步步丰满起来. 0-添加依赖 1-建一个servlet 2-web.xml中添加servlet声明 3-重新运 ...

  4. 历年NOIP水题泛做

    快noip了就乱做一下历年的noip题目咯.. noip2014 飞扬的小鸟 其实这道题并不是很难,但是就有点难搞 听说男神错了一个小时.. 就是$f_{i,j}$表示在第$i$个位置高度为$j$的时 ...

  5. 工厂模式(Factory)

    一.分类 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式主要分为三个,简单工厂模式(Simple Factory)/ 工厂方法模式(Fac ...

  6. Linux(Ubuntu) Mysql的安装配置例子以及常用命令

    1.安装配置例子 有空再写 2.注意事项 (1)启动mysql 在/etc/mysql 目录下 service mysql start  新版本是(service mysqld start  ) (2 ...

  7. 干货!IT小伙伴们实用的网站及工具大集合!持续更新!

    1.Git 还在担心自己辛辛苦苦写的代码被误删了吗?还在担心自己改错了代码不能挽回吗?还在苦恼于多人开发合作找不到一个好的工具吗?那么用Git就对 了,Git是一个开源的分布式版本控制系统,用以有效. ...

  8. travis CI

    travis可对多语言持续继承,本文以nodejs 为例. 首先添加文件.travis.yml 中language: node_jsnode_js:  - "6"  - " ...

  9. python lxml install

    之前记得安装libxslt和libxml yum install libxml* -yyum install libxslt* -y wget http://lxml.de/files/lxml-3. ...

  10. 关于ajax为什么会返回php整个源码

    ajax 程序:返回的是php文件输出的代码. 1. 注意:如果你的php文件包含了html代码或者说是输出了HTML代码,它都会返回给 AJAX. 2. 注意:是整个php文件.这意味着如果你的aj ...