问题描述
以下是该方案:
我的用户会看到一个网格,基本上是电子表格的精简版。网格中的每一行都有文本框。当他们更改文本框中的值时,我正在对其输入执行验证,更新驱动网格的集合,并重新绘制页面上的小计。这全部由每个文本框的OnChange事件处理。
当他们点击保存按钮时,我正在使用按钮的OnClick事件来执行一些最终验证。金额,然后将他们的整个输入发送到Web服务,保存它。
至少,如果他们通过表单选中提交按钮会发生这种情况。 / p>
问题是,如果输入值,则立即单击保存按钮,SaveForm()在UserInputChanged()完成之前开始执行 - 竞争条件。我的代码不使用setTimeout,但是我用它来模拟缓慢的UserInputChanged验证码:
<! - 剪辑 - >
< script>
var amount = null;
var currentControl = null;
函数UserInputChanged(control){
currentControl = control;
//使用setTimeout来模拟慢速验证代码(生产代码不使用setTimeout)
setTimeout(ValidateAmount(),100);
}
函数SaveForm(){
//调用web服务以保存值
document.getElementById(SavedAmount)。innerHTML = amount;
}
函数ValidateAmount(){
//这里的各种validationey函数
amount = currentControl.value; //将值保存到集合
document.getElementById(Subtotal)。innerHTML = amount; //更新小计
}
< / script>
<! - snip - >
金额:< input type =textid =UserInputValueonchange =UserInputChanged(this); /> < br />
小计:< span id =小计>< / span> < br />
< input type =buttononclick =SaveForm(); value =保存/> < br />< br />
已保存金额:< span id =SavedAmount>< / span>
<! - snip - >
我认为我不能加快验证码 - 它非常轻巧,但显然,在验证完成之前代码试图调用Web服务的速度足够慢。
在我的机器上,~95ms是验证代码在保存之前执行之间的幻数代码开始了。根据用户的计算机速度,这可能更高或更低。
有没有人有任何想法如何处理这种情况?一位同事建议在验证代码运行时使用信号量,并在保存代码中使用繁忙循环等待信号量解锁 - 但我想避免在我的代码中使用任何类型的繁忙循环。
使用信号量(我们称之为StillNeedsValidating)。如果SaveForm函数看到StillNeedsValidating信号量已启动,请让它激活自己的第二个信号量(我在这里称之为FormNeedsSaving)并返回。验证函数完成后,如果FormNeedsSaving信号量已启动,它将自行调用SaveForm函数。
在jankcode中;
function UserInputChanged(control){
StillNeedsValidating = true;
//做验证
StillNeedsValidating = false;
if(FormNeedsSaving)saveForm();
}
函数SaveForm(){
if(StillNeedsValidating){FormNeedsSaving = true;返回; }
//调用Web服务来保存值
FormNeedsSaving = false;
}
Here's the scenario:
My users are presented a grid, basically, a stripped down version of a spreadsheet. There are textboxes in each row in the grid. When they change a value in a textbox, I'm performing validation on their input, updating the collection that's driving the grid, and redrawing the subtotals on the page. This is all handled by the OnChange event of each textbox.
When they click the "Save" button, I'm using the button's OnClick event to perform some final validation on the amounts, and then send their entire input to a web service, saving it.
At least, that's what happens if they tab through the form to the Submit button.
The problem is, if they enter a value, then immediately click the save button, SaveForm() starts executing before UserInputChanged() completes -- a race condition. My code does not use setTimeout, but I'm using it to simulate the sluggish UserInputChanged validation code:
<!-- snip -->
<script>
var amount = null;
var currentControl = null;
function UserInputChanged(control) {
currentControl = control;
// use setTimeout to simulate slow validation code (production code does not use setTimeout)
setTimeout("ValidateAmount()", 100);
}
function SaveForm() {
// call web service to save value
document.getElementById("SavedAmount").innerHTML = amount;
}
function ValidateAmount() {
// various validationey functions here
amount = currentControl.value; // save value to collection
document.getElementById("Subtotal").innerHTML = amount; // update subtotals
}
</script>
<!-- snip -->
Amount: <input type="text" id="UserInputValue" onchange="UserInputChanged(this);" /> <br />
Subtotal: <span id="Subtotal"></span> <br />
<input type="button" onclick="SaveForm();" value="Save" /> <br /><br />
Saved amount: <span id="SavedAmount"></span>
<!-- snip -->
I don't think I can speed up the validation code -- it's pretty lightweight, but apparently, slow enough that code tries to call the web service before the validation is complete.
On my machine, ~95ms is the magic number between whether the validation code executes before the save code begins. This may be higher or lower depending on the users' computer speed.
Does anyone have any ideas how to handle this condition? A coworker suggested using a semaphore while the validation code is running and a busy loop in the save code to wait until the semaphore unlocks -- but I'd like to avoid using any sort of busy loop in my code.
Use the semaphore (let's call it StillNeedsValidating). if the SaveForm function sees the StillNeedsValidating semaphore is up, have it activate a second semaphore of its own (which I'll call FormNeedsSaving here) and return. When the validation function finishes, if the FormNeedsSaving semaphore is up, it calls the SaveForm function on its own.
In jankcode;
function UserInputChanged(control) {
StillNeedsValidating = true;
// do validation
StillNeedsValidating = false;
if (FormNeedsSaving) saveForm();
}
function SaveForm() {
if (StillNeedsValidating) { FormNeedsSaving=true; return; }
// call web service to save value
FormNeedsSaving = false;
}
这篇关于避免javascript竞争条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!