我可以控制javascript/jQuery事件的触发顺序吗?

我可以控制javascript/jQuery事件的触发顺序吗?,javascript,jquery,asp.net,webforms,Javascript,Jquery,Asp.net,Webforms,背景 我有一个带有网格的asp.net webform,当用户更新该网格中的文本框时,onchange事件启动WebMethod调用并更新其余更改的行。当时没有保存任何内容--我们只是更新UI 要提交更改,请单击“保存”按钮 这实际上在几乎所有场景中都能可靠地工作。然而,有一个非常顽固的问题,我觉得我应该能够解决,但现在是时候请专家了 问题场景 我使用jQuery捕获enter键,不幸的是,该事件首先触发,导致页面在回调完成之前提交。该行未正确更新。过时和令人困惑的数据被保存 更新 我不认为您可

背景

我有一个带有网格的asp.net webform,当用户更新该网格中的文本框时,onchange事件启动WebMethod调用并更新其余更改的行。当时没有保存任何内容--我们只是更新UI

要提交更改,请单击“保存”按钮

这实际上在几乎所有场景中都能可靠地工作。然而,有一个非常顽固的问题,我觉得我应该能够解决,但现在是时候请专家了

问题场景

我使用jQuery捕获enter键,不幸的是,该事件首先触发,导致页面在回调完成之前提交。该行未正确更新。过时和令人困惑的数据被保存

更新

我不认为您可以使enter行为依赖于回调,因为您可以在不更改行的情况下保存。在这种情况下,如果不更改行,它将永远不会保存

现在,如果有某种方法来检查javascript的内部任务列表,或者创建自己的,然后以某种方式进行管理,那就行了。但这对一些本应该很容易的事情来说是一件沉重的事情。因此,除非专家告诉我其他情况,否则我必须假设这是错误的

尝试

现在,我正在使用内置的jQuery事件,我得到了这个精心设计的setTimeout,它坚持了一个事实,即尝试保存,暂停足够长的时间,使WebMethod至少能够被调用,并依赖回调来完成提交。但事实证明javascript ansychrony并没有像我希望的那样工作,onchange事件甚至在代码块完成之前都不会触发。这令人惊讶

我在想我可以用我自己的小对象把这些事件按正确的顺序排成一列,然后找到一个聪明的方法来触发它,等等

这一切似乎都是错误的方向。当然这是疯狂的过度使用,这是一个常见的问题,我忽略了一个简单的解决方案,因为我不使用javascript 24/7

对吧?

代码

这就是我现在所做的。这显然不起作用——我试图利用jquery的异步特性,但所有这些显然都必须在行的onchange事件触发之前结束:

$(document).bind("keypress", function (e) {
    if (e.keyCode == 13) {
        handleEnter();
        return false; //apparently I should be using e.preventDefault() here. 
    }
});


function handleEnter() {
    setTimeout(function () {
        if (recalculatingRow) { //recalculatingRow is a bit managed by the onchange code.
            alert('recalculating...');
            return true; //recur
        }

        //$('input[id$="ButtonSave"]').click();
        alert('no longer recalculating. click!');
        return false;
    }, 1000);
}
然后典型的一排像这样。请注意,我没有使用jquery来绑定:

 <input name="ctl00$MainContent$GridOrderItems$ctl02$TextOrderItemDose" type="text" value="200.00" maxlength="7" id="ctl00_MainContent_GridOrderItems_ctl02_TextOrderItemDose" onchange="recalculateOrderItemRow(this);" style="width:50px;" />

我可以发布重新计算OrderItemRow的代码,但它确实很长,而现在的问题是它在after keypress事件结束之前不会启动

更新Dos
根据(man是一篇很酷的文章)的说法,setTimeout的使用应该会使它变成异步的。进一步挖掘setTimeout和jQuery之间的交互,以及普通javascript事件和jQuery事件之间的交互

你能发布你的javascript吗?听起来你走对了。在进行AJAX调用之前,我会更改OnChange事件以增加变量。我将在进程中调用变量并将其初始化为零。当AJAX调用返回时,我会将inProcess更新为当前值减去1。在Enter key事件中,我将检查inProcess是否等于零。如果没有,您可以警告用户或设置超时以稍后重试

你能发布你的javascript吗?听起来你走对了。在进行AJAX调用之前,我会更改OnChange事件以增加变量。我将在进程中调用变量并将其初始化为零。当AJAX调用返回时,我会将inProcess更新为当前值减去1。在Enter key事件中,我将检查inProcess是否等于零。如果没有,您可以警告用户或设置超时以稍后重试

听起来您不应该异步调用WebMethod。同步调用它,成功后保存数据。

听起来不应该异步调用WebMethod。同步调用它,成功后保存数据。

您可以在onChange事件中解除Enter键捕获的绑定,然后在回调函数结束时重新绑定它。如果您发布一些代码,我可以给出更具体的答案。

您可以在onChange事件中解除对Enter键捕获的绑定,然后在回调函数结束时重新绑定它。如果你发布一些代码,我可以给出一个更具体的答案。

阻止进入不应该给你带来这么多麻烦!确保代码中有类似的内容:

$(document).on('keydown', 'input', function(e) {
    if(e.keyCode == 13) {
       e.preventDefault();
    }
});
更新

看起来您确实想在回车时保存,但只有在用户界面在
change
上更新后才能保存。这是可能的。您可以使用上面Matthew Blancarte建议的标志,从
更改
回调触发save,并摆脱
设置超时

但我不建议这样做您最好仅依靠“保存”按钮进行保存。如果不这样做,用户将不得不等待两个异步操作完成,然后才能完成保存。因此,您必须阻止UI,或者跟踪所有异步操作,根据需要中止一些操作。我认为这不值得,如果保存时间太长,ENTER对用户来说会变得不那么直观。

阻止ENTER应该不会给您带来这么多麻烦!确保代码中有类似的内容:

$(document).on('keydown', 'input', function(e) {
    if(e.keyCode == 13) {
       e.preventDefault();
    }
});
更新

看起来您确实想在回车时保存,但只有在用户界面在
change
上更新后才能保存。这是可能的。您可以使用上面Matthew Blancarte建议的标志,从
更改
回调触发save,并摆脱
设置超时

但我不建议这样做您最好仅依靠“保存”按钮进行保存。如果您不这样做,您的用户将不得不等待
function recalculateOrderItemRow(textbox) {
    //I'm hiding a lot of code that gathers and validates form data. There is a ton and it's not interesting.

    //Call the WebMethod on the server to calculate the row. This will trigger a callback when complete.
    PageMethods.RecalculateOrderItemRow($(textbox).attr('id'),
                                   orderItemDose,
                                   ProductItemSize,
                                   orderItemUnits,
                                   orderItemUnitPrice,
                                   onRecalculateOrderItemRowComplete);

}
function onRecalculateOrderItemRowComplete(result) {
    var sender, row;

    sender = $('input[id="' + result.Sender + '"]');
    row = $(sender).closest('tr');

    row.find('input[id$="TextOrderItemDose"]').val(result.Dose);
    row.find('input[id$="TextOrderItemUnits"]').val(result.Units);
    row.find('span[id$="SpanTotalPrice"]').html(formatCurrency(result.TotalPrice));

    calculateGrandTotalPrice();
    $(document.activeElement).select();

    if (isSaving && saveOnID == result.Sender) {
        forceSave();
    }
}