我正在尝试创建一个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
,如果我多次更改选择,则computed
只会在5秒钟后开始显示当前选定的内容。值。这几乎可以完成我想要的事情,但是一个问题是,第一次更改下拉列表时,您不必等待5秒钟-它应该立即进行JSON调用。速率限制是在第一个更改到5秒后的 之间停止进一步的JSON请求。那么如何使它立即执行JSON请求并更新 first 更改?
答案 0 :(得分:0)
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秒的延迟。
答案 1 :(得分:0)
有趣的问题。我开始使用它,得出的结论是您需要为此定制一个扩展器。 I found one模拟了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>
在第一个文本框中输入文本后,请注意在其他文本框中如何立即进行更改。但是,第一个更改之后的任何更改都会被延迟
借助此方法,您可以扩展可观察值和计算可观察值。