簡體   English   中英

使用AJAX更新來限制淘汰率

[英]Knockout rate limiting with AJAX updates

我正在嘗試創建一個HTML表單,該表單根據下拉列表中選擇的內容來更新其某些值。 視圖模型如下所示:

function RoomViewModel() {
    var self = this;

    self.companyOptions = @Html.Raw({ ... });
    self.companyValue = ko.observable().extend({ rateLimit: 5000 });
    self.companyInfo = ko.observable();
    ko.computed(function() {
        if (self.companyValue()) {
            $.getJSON('@Html.GenerateActionLinkUrl("GetCompanyAndPlans")', {}, self.companyInfo);
        }
    });
}

ko.options.deferUpdates = true;
ko.applyBindings(new RoomViewModel());

然后,將我的select下拉列表綁定到companyValue ,如果我多次更改了選擇,則僅在5秒鍾后, computed插入值就會顯示並顯示當前選定的值。 這幾乎可以完成我想要的事情,但是一個問題是,第一次更改下拉列表時,您不必等待5秒鍾-它應該立即進行JSON調用。 速率限制是第一次更改到5秒后停止進一步的JSON請求。 那么,如何使它立即執行JSON請求並為第一個更改進行更新?

var ratelim = 0; // global rate limit 

function RoomViewModel() {
    var self = this;

    self.companyOptions = @Html.Raw({ ... });

    if(ratelim == 0){
      self.companyValue = ko.observable().extend({ rateLimit: ratelim }); // trigger the change without a delay 
      ratelim = 5000; // update the ratelim so the next request has a 5 second delay 
    } else { // ratelimit is not 0 (not first request), go ahead with regular rate-limited change: 
      self.companyValue = ko.observable().extend({ rateLimit: ratelim }); // extend the observable, with current ratelim
    }

    self.companyInfo = ko.observable();
    ko.computed(function() {
        if (self.companyValue()) {
            $.getJSON('@Html.GenerateActionLinkUrl("GetCompanyAndPlans")', {}, self.companyInfo);
        }
    });
}

ko.options.deferUpdates = true;
ko.applyBindings(new RoomViewModel());

我相信這應該可以解決問題。 我使用了一個全局變量(ratelim)來允許您的函數檢測它是否是第一個請求...確實,您應該將true或false的變量值更改為是否正在進行請求,以便有0速率限制(如果用戶已經閑置了一段時間)。 再說一遍,如果第二個請求發生在第一個請求之后20秒,則無需再有5秒的延遲。

有趣的問題。 我開始使用它,得出的結論是您需要為此定制一個擴展器。 我找到了一個模擬rateLimit的軟件,並進行了一些更改,似乎確實可以滿足您的需求。

有了這個,您應該可以做到:

self.companyValue = ko.observable().extend({ customRateLimit: 5000 });

並具有初始更改是即時的,任何后續更改都將受到速率的限制。

這是小提琴

這是可運行的代碼段:

 ko.extenders.customRateLimit = function(target, timeout) { var writeTimeoutInstance = null; var currentValue = target(); var updateValueAgain = false; var interceptor; var isFirstTime = true if (ko.isComputed(target) && !ko.isWriteableObservable(target)) { interceptor = ko.observable().extend({ customRateLimit: timeout }); target.subscribe(interceptor); return interceptor; } return ko.dependentObservable({ read: target, write: function(value) { var updateValue = function(value) { if (isFirstTime) { target(value); isFirstTime = false; } else { if (!writeTimeoutInstance) { writeTimeoutInstance = setTimeout(function() { writeTimeoutInstance = null; if (updateValueAgain) { updateValueAgain = false; updateValue(currentValue); } target(value); }, timeout); } } } currentValue = value; if (!writeTimeoutInstance) updateValue(currentValue); else updateValueAgain = true; } }); } function AppViewModel() { this.text = ko.observable().extend({ customRateLimit: 1000 }); this.rateLimited = ko.computed(this.text).extend({ customRateLimit: 1000 }); } ko.applyBindings(new AppViewModel()); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js"></script> <h4>Change value is default so move the focus out of the input to change values.</h4> <div> Enter Text: <input type='text' data-bind='value: text' /> </div> <div> Rete Limited <small>(after the first change)</small>: <input type='text' data-bind='value: text' /> </div> <div> Rete Limited Computed <small>(after the first change)</small>: <input type='text' data-bind='value: rateLimited' /> </div> 

注意,在第一個文本框中輸入文本后,其他更改立即生效。 但是,第一個更改之后的任何更改都會延遲

這樣,您可以擴展可觀察值和計算可觀察值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM