Knockout Rate limit: Rate-limiting observable notifications, apratelimiting

Source: Internet
Author: User

Knockout Rate limit: Rate-limiting observable notifications, apratelimiting

Rate limit, observed notification

Original article: Rate-limiting observable communications

Chinese and English terms:

  • Observability -- observable
  • Computable observation -- computed observable
  • Speed limit -- rate-limit
Note: This speed limit API is added in Knockout 3.1.0. For earlier versions, throttle extender provides similar functions.
Generally, an observable is immediately notified to its subscriber after it is changed, so that any computed observables or dependent on ObservabilityIs synchronously updated. However, the rate limit (rateLimit) extender promotes ObservabilitySuppression and delay change the notification period for a specified period of time. A speed limit can be observed so that the asynchronous update dependency is observed.
Rate limit extenders can be applied to any type of observation, including ObservabilityArray (observable arrays) and Computing Observability(Computed observables ). The main use cases of rate limit are:
  • Response after a delay
  • Combine multiple changes to a single update

Application speed limit Extender

The speed limit supports two parameter formats:
// Shorthand: Specify just a timeout in millisecondssomeObservableOrComputed.extend({ rateLimit: 500 }); // Longhand: Specify timeout and/or methodsomeObservableOrComputed.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });
When a notification is triggered, the preceding method can be controlled as follows to receive the following values:
1. yyatfixedrate -- If there are no other default values. At this time, the notification occurs from the first change to the observed period (or initially or from the previous notification.
2. notifyWhenChangesStop -- after the specified period ObservabilityIt does not change. Each time ObservabilityThe timer is reset. ObservabilityThe notification does not occur when the change is more frequent than the previous period.

Example 1: Basic
Consider the following code for observation:
var name = ko.observable('Bert'); var upperCaseName = ko.computed(function() {    return name().toUpperCase();});
Normally, if you change the name as follows:
name('The New Bert');
Then, upperCaseName will be re-calculated immediately before your next line of code runs. But if you use rateLimit to replace the name definition, see the following code:
var name = ko.observable('Bert').extend({ rateLimit: 500 });
When the name changes, the upperCaseName will not be re-calculated immediately, but will wait 500 milliseconds (half a second) until the new value is notified to the upperCaseName ), then recalculate its value. No matter how many times the name is changed during MS, upperCaseName will be updated only once using the latest value.

Example 2: Do something when the user stops typing
In this online example, there is an instantaneousValue that can be observed and will immediately respond when you press the next key. This is wrapped in a delayedValue Computing ObservabilityIn the configuration, the notifyWhenChangesStop speed limit method is used only to notify the change after 400 milliseconds of stop.
Try this ( Note: This example is not running and is only for demonstration.):

Type stuff here:

Current delayed value:Sdfssdsdfssdfdsffffff

Stuff you have typed:
  • Sdfssd
  • Sdfssdsdfs
  • Sdfssdsdfssdfdsffffff

Source code: View
<p>Type stuff here: <input data-bind='value: instantaneousValue,    valueUpdate: ["input", "afterkeydown"]' /></p><p>Current delayed value: <b data-bind='text: delayedValue'> </b></p> <div data-bind="visible: loggedValues().length > 0">    
Source code: View model

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());

Note ):

Assume that the time set for timeout is t, then:

  • Method: "yywhenchangesstop" is used to reset the timer when the timer has not expired. If the timer is still not typed after t, the notification event is triggered;
  • If method: "yywhenchangesstop" is not used, the timer is not cleared, and the notification event is triggered at every t moment. Therefore, a notification is triggered when the t time is not exceeded.

Example 3: Avoid Multiple Ajax requests

The following model shows the data you can draw as a page table (paged grid:
function GridViewModel() {    this.pageSize = ko.observable(20);    this.pageIndex = ko.observable(1);    this.currentPageData = ko.observableArray();     // Query /Some/Json/Service whenever pageIndex or pageSize changes,    // and use the results to update currentPageData    ko.computed(function() {        var params = { page: this.pageIndex(), size: this.pageSize() };        $.getJSON('/Some/Json/Service', params, this.currentPageData);    }, this);}
Because Calculation ObservabilityThe pageIndex and pageSize values become dependent on them. Therefore, when a GridViewModel is first instantiated and the pageIndex or pageSize attribute is changed later, this Code uses jQuery's $. getJSON function to reload currentPageData.

This is very simple and concise (adding more observed query parameters will trigger an automatic refresh at any time), but there is a potential efficiency problem, suppose you add the following function to GridViewModel to change pageIndex and pageSize:
this.setPageSize = function(newPageSize) {    // Whenever you change the page size, we always reset the page index to 1    this.pageSize(newPageSize);    this.pageIndex(1);}
The problem is that two Ajax requests are triggered: the first one starts when you update pageSize, and the second one starts when you update pageIndex. This is a waste of bandwidth and server resources and the root cause of unpredictable competition conditions.
When you apply Computing ObservabilityThe rateLimit extender also avoids extra calculation functions. Use a short speed limit period (for example, 0 ms) to ensure that any sequence of dependent synchronization changes triggers only one observed evaluation of your computing. For example:
ko.computed(function() {    // This evaluation logic is exactly the same as before    var params = { page: this.pageIndex(), size: this.pageSize() };    $.getJSON('/Some/Json/Service', params, this.currentPageData);}, this).extend({ rateLimit: 0 });

Now you can change the pageIndex and pageSize no matter how many times, this Ajax will only be called once, when you publish your thread to the JavaScript background for running.

Computing special observed conditions

ForComputing ObservabilityFor example, whenComputing Observability, Instead of changing the value,Speed LimitTriggered.Computing ObservabilityThe value is not re-evaluated until it is actually changed-after the change notification occurs, or when the calculated observed value is directly accessed. If you need to access the nearest evaluate of this computation, you can use the peek method.

Forced rate limit: always notifies subscribers.
When any ObservabilityWhen the value is of the native type (number, string, boolean, or null), only when it is set to a true different from the previous value, ObservabilityIs notified by default. Therefore, at the end of this period, the native Value Speed LimitObserved notifications only when their values are really different, in other words, if a native value rate limit can be observed to be changed to a new value, and then changed back to the original value at the end of this period, the notification does not occur.
If you want to ensure that the subscriber is always notified of updates, even if the value is the same, you should use the notifiy extender except rateLimit:
myViewModel.fullName = ko.computed(function() {    return myViewModel.firstName() + " " + myViewModel.lastName();}).extend({ notify: 'always', rateLimit: 500 });

Comparison with throttle extenders

If you want to port code from the discarded throttle extender, pay attention to the following method. The rateLimit extender is different from the throttle extender.
When rateLimit is used:
1. Writing to observability is not delayed; the observed values can be correctly updated. The writable computation can be observed, which means that the write function is always correctly run.
2. All change notifications are delayed, including when valueHasMuted is manually called. This means that you cannot use valueHasMutated to force a rate limit. You can observe to notify a value that has not changed.
3. The default rate limit method is different from the throttle algorithm. Use the yywhenchangesstop method to match the throttle action.
4. For rate limit calculation, we can observe that the value is not a rate limit. If you read the value, it will be recalculated.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.