下面的情况:

我的用户被呈现网格,基本上,电子表格的一个精简版本。有网格中的每一行文本框。当他们在一个文本框更改值,我对他们的输入执行验证,该更新的驾驶电网的收集,并重新绘制页面上的小计。这是所有由每个文本框的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之间是保存代码开始之前验证代码是否执行幻数。这可以根据用户的计算机的速度是高或低。

没有人有任何想法如何处理这种情况?使用而验证代码运行一个信号,并在节省代码繁忙的循环,等到信号解锁一个同事建议 - 但我想避免使用任何形式的忙循环的在我的代码

有帮助吗?

解决方案

使用信号灯(姑且称之为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;
}

其他提示

验证过程中禁用保存按钮。 它设置为禁用的第一件事验证确实,并且作为它完成重新启用它。

e.g。

function UserInputChanged(control) {
    // --> disable button here --< 
    currentControl = control;
    // use setTimeout to simulate slow validation code (production code does not use setTimeout)
    setTimeout("ValidateAmount()", 100); 
}

function ValidateAmount() {
    // various validationey functions here
    amount = currentControl.value; // save value to collection
    document.getElementById("Subtotal").innerHTML = amount; // update subtotals
    // --> enable button here if validation passes --<
}

您必须在您删除setTimeout并验证一个功能,但除非你的用户有超人的反应能力,你要善于去调节。

我觉得超时造成您的问题......如果这将是普通的代码(没有异步AJAX调用,超时等),然后我不认为UserInputChanged完成之前SaveForm将被执行。

一个信号量或互斥体可能是最好的方式,但不是一个繁忙的循环,只是用一种setTimeout()来模拟一个线程睡眠。像这样:

busy = false;

function UserInputChanged(control) {
    busy = true;
    currentControl = control;
    // use setTimeout to simulate slow validation code (production code does not use setTimeout)
    setTimeout("ValidateAmount()", 100); 
}

function SaveForm() {
    if(busy) 
    {
       setTimeout("SaveForm()", 10);
       return;
    }

    // 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
    busy = false;
}

您可以设置一个用于监视整个电网的状态并提高其指示整个网格是否有效或不是一个事件的重复的功能。

基于该状态你“提交表单”按钮会然后启用或禁用本身。

哦,我现在看到了类似的反应 - 那也有用,当然

在与异步数据源的工作就肯定能有竞争条件,因为JavaScript的进程线程继续执行,这可能取决于还未从远程数据源返回的数据指令。这就是为什么我们有回调函数。

在你的榜样,在调用验证代码需要有一个回调函数,可以做一些事情的时候验证的回报。

然而,使复杂逻辑的东西或试图解决或增强现有系列的回调时,你可以去坚果。

这是我所创建的原-Q库的原因: http://code.google的.com / p /原q /

检查出来,如果你做了很多这种类型的工作的。

您没有竞争状态,种族条件不能在JavaScript发生由于JavaScript是单线程的,因此2个线程不能相互干扰。

这是你给是不是一个很好的例子的例子。 setTimeout调用将把调用的函数在队列中的JavaScript引擎,并在以后执行它。如果在这一点上您单击保存按钮,该setTimeout函数将不会被调用,直到保存后彻底完成。

什么是可能在你的JavaScript情况是,onClick事件是由JavaScript引擎称为被称为onChange事件之前。

作为一个提示,要记住,JavaScript是单线程的,除非使用JavaScript调试器(萤火虫,微软screipt调试器)。这些程序拦截线和暂停。从其他线程上该点(通过事件的setTimeout呼叫或XMLHttp的处理程序)可以运行,使得它似乎JavaScript可以同时运行多个线程。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top