这是场景:
向我的用户显示了一个网格,基本上是一个电子表格的精简版本。网格中的每一行都有文本框。当他们在文本框中更改值时,我将对其输入执行验证,更新驱动网格的集合,并在页面上重新绘制小计。所有这些都由每个文本框的OnChange事件处理。
当他们单击“保存”按钮时,我正在使用按钮的OnClick事件对金额执行一些最终验证,然后将其全部输入发送到Web服务,进行保存。
至少,如果他们在表单中选择“提交”按钮,就会发生这种情况。
问题是,如果他们输入一个值,然后立即单击保存按钮,则SaveForm()在UserInputChanged()完成之前开始执行-这是一种竞争条件。我的代码没有使用setTimeout,但是我正在使用它来模拟缓慢的UserInputChanged验证代码:
<!-- 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 -->
我认为我无法加快验证代码的速度-它相当轻巧,但是显然,它的速度很慢,以至于代码在验证完成之前会尝试调用Web服务。
在我的机器上,〜95ms是在保存代码开始之前验证代码是否执行之间的魔数(Magic Number)。取决于用户的计算机速度,它可能更高或更低。
有谁知道如何处理这种情况?一位同事建议在验证代码运行时使用信号量,并在保存代码中使用繁忙循环,直到信号量解锁为止-但我想避免在我的代码中使用任何形式的繁忙循环。
最佳答案
使用信号量(我们称它为StillNeedsValidating)。如果SaveForm函数看到StillNeedsValidating信号量已启动,请它激活它自己的第二个信号量(在这里将其称为FormNeedsSaving)并返回。验证函数完成后,如果FormNeedsSaving信号量打开,它将自行调用SaveForm函数。
用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;
}