注意:这个速率限制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. SQLServer生成三位姓名及11位国内电话号码(生成测试数据用)

    SELECT SUBSTRING(N'王李张刘陈杨黄赵吴周徐孙马朱胡郭何高林郑谢罗梁宋唐许韩冯邓曹彭曾肖田董袁潘于蒋蔡余杜叶程苏魏吕丁任沈姚卢姜崔钟谭陆汪范金石廖贾夏韦付方白邹孟熊秦邱江尹薛闫段雷侯龙 ...

  2. 【ORACLE】ORA-12537 问题整理

    ORA-12537主要是ORALCE 监听问题,今天帮同事处理问题时,他问道一种情况,开始连接很正常,后续多次出现ORA-12537问题 简单整理了下 一般请况下 1-检查数据库服务器是否没有启动监听 ...

  3. PHP 随手记

    这篇文章用来记录自己学习PHP过程中遇到的问题以及解决方法,随时遇到新的问题都会更新,方便以后查阅. 环境:ubuntu 14.10,php5,apache2 1.如何打开PHP报错信息? 解决方法: ...

  4. [IOS]swift 使用AVOS的API

    避免写后台代码,但保证app能够有后台,使用了AVOS这个产品来帮助自己的app联网,AVOS是很强大的云服务,基本原理和Parse差不多,只是parse在国外可能对国内用户联网速度上有点限制. 下面 ...

  5. 初学者-PHP笔记

    PHP介绍 PHP 是 "PHP Hypertext Preprocessor" 的首字母缩略词 PHP 是一种被广泛使用的开源脚本语言 PHP 脚本在服务器上执行 PHP 没有成 ...

  6. dnslog注入

    使用Powershell反弹Meterpreter Shell cloudeye在windows下的应用 今天突发奇想的一个姿势,算不上什么技巧,分享一下吧. 看到有人问过.http://zone.w ...

  7. android 之HttpURLConnection的post,get方式请求数据

    get方式和post方式的区别: 1.请求的URL地址不同: post:"http://xx:8081//servlet/LoginServlet" get:http://xxx: ...

  8. IOS第四天-新浪微博 -存储优化OAuth授权账号信息,下拉刷新,字典转模型

    *************application - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOpti ...

  9. norm函数的作用,matlab

    格式:n=norm(A,p)功能:norm函数可计算几种不同类型的返回A中最大一列和,即max(sum(abs(A))) 2 返回A的最大奇异值,和n=norm(A)用法一样 inf 返回A中最大一行 ...

  10. C# Winform中如何让PictureBox的背景透明

    最近做winform程序,其中有个需求:有两个PictureBox完全重叠,上面一个需要透明,不能遮挡下面的,以为设置上面的BackColor为透明色就可以了,结果不行,上网搜了一下,发现对于我这种需 ...