注意:这个速率限制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. BestCoder#51

    #include <cstdio> #include <iostream> #include <cmath> #include <cstring> us ...

  2. jQuery Ajax请求(关于火狐下SyntaxError: missing ] after element list ajax返回json,var json = eval("("+data+")"); 报错)

    $.ajax({    contentType: "application/x-www-form-urlencoded;charset=UTF-8" ,    type: &quo ...

  3. 创建WP8试用应用

    参考资料: 创建 Windows Phone 的试用应用 如何在 Windows Phone 应用中实现试用体验 Windows Phone 7 开发 31 日谈——第23日:提供试用版应用程序 对资 ...

  4. WP8解析XML格式文件

    DOTA2 WebAPI请求返回的格式有两种,一种是XML,一种是JSON,默认是返回JSON格式,如果要返回XML格式的话,需要在加上format=xml. 这里举一个简单的解析XML格式的例子(更 ...

  5. [翻译svg教程]svg 中的g元素

    svg 中的<g>元素用来组织svg元素.如果一组svg元素被g元素包裹了,你可以通过对g元素进行变换(transform),被g元素包裹的元素也将被变换,就好这些被svg包裹的元素是一个 ...

  6. 【BZOJ3314】 [Usaco2013 Nov]Crowded Cows 单调队列

    第一次写单调队列太垃圾... 左右各扫一遍即可. #include <iostream> #include <cstdio> #include <cstring> ...

  7. Xpath基础语法学习

    背景: 之所以学习Xpath,是因为在学习selenium定位页面元素,总是定位不到元素.为了更好的开展自动化测试,先学习下Xpath. 一:Xpath是什么. 1:Xpath是一门在XML文档中查找 ...

  8. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  9. [转]FINDSTR正则表达式小结

    前言:最近写了一个bat用于快速编译swf至目标目录,想利用FINDSTR命令通过匹配目标目录名称,匹配数量大概600多个,发现匹配耗时比较久,大概花费10余秒,因此还是放弃字符匹配,乖乖拼出全称来定 ...

  10. iOS开发之记录用户登录状态

    iOS开发之记录用户登录状态 我们知道:CoreData的配置和使用步骤还是挺复杂的.但熟悉CoreData的使用流程后,CoreData还是蛮好用的.今天要说的是如何记录我们用户的登陆状态.例如微信 ...