我可以控制javascript/jQuery事件的触发顺序吗?
背景 我有一个带有网格的asp.net webform,当用户更新该网格中的文本框时,onchange事件启动WebMethod调用并更新其余更改的行。当时没有保存任何内容--我们只是更新UI 要提交更改,请单击“保存”按钮 这实际上在几乎所有场景中都能可靠地工作。然而,有一个非常顽固的问题,我觉得我应该能够解决,但现在是时候请专家了 问题场景 我使用jQuery捕获enter键,不幸的是,该事件首先触发,导致页面在回调完成之前提交。该行未正确更新。过时和令人困惑的数据被保存 更新 我不认为您可以使enter行为依赖于回调,因为您可以在不更改行的情况下保存。在这种情况下,如果不更改行,它将永远不会保存 现在,如果有某种方法来检查javascript的内部任务列表,或者创建自己的,然后以某种方式进行管理,那就行了。但这对一些本应该很容易的事情来说是一件沉重的事情。因此,除非专家告诉我其他情况,否则我必须假设这是错误的 尝试 现在,我正在使用内置的jQuery事件,我得到了这个精心设计的setTimeout,它坚持了一个事实,即尝试保存,暂停足够长的时间,使WebMethod至少能够被调用,并依赖回调来完成提交。但事实证明javascript ansychrony并没有像我希望的那样工作,onchange事件甚至在代码块完成之前都不会触发。这令人惊讶 我在想我可以用我自己的小对象把这些事件按正确的顺序排成一列,然后找到一个聪明的方法来触发它,等等 这一切似乎都是错误的方向。当然这是疯狂的过度使用,这是一个常见的问题,我忽略了一个简单的解决方案,因为我不使用javascript 24/7 对吧? 代码 这就是我现在所做的。这显然不起作用——我试图利用jquery的异步特性,但所有这些显然都必须在行的onchange事件触发之前结束:我可以控制javascript/jQuery事件的触发顺序吗?,javascript,jquery,asp.net,webforms,Javascript,Jquery,Asp.net,Webforms,背景 我有一个带有网格的asp.net webform,当用户更新该网格中的文本框时,onchange事件启动WebMethod调用并更新其余更改的行。当时没有保存任何内容--我们只是更新UI 要提交更改,请单击“保存”按钮 这实际上在几乎所有场景中都能可靠地工作。然而,有一个非常顽固的问题,我觉得我应该能够解决,但现在是时候请专家了 问题场景 我使用jQuery捕获enter键,不幸的是,该事件首先触发,导致页面在回调完成之前提交。该行未正确更新。过时和令人困惑的数据被保存 更新 我不认为您可
$(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();
}
}