Javascript 动作方法执行序列
我陷入了一个非常奇怪的境地。解释起来很复杂,但我会尽力的 我有一个带有4导航的UIJavascript 动作方法执行序列,javascript,c#,jquery,asp.net-mvc,model-view-controller,Javascript,C#,Jquery,Asp.net Mvc,Model View Controller,我陷入了一个非常奇怪的境地。解释起来很复杂,但我会尽力的 我有一个带有4导航的UI 表单在MVC中使用Ajax.BeginForm构建 对于顶部的每个导航链接元素,我都有一个JavaScript函数 var LoadTabs = function (e, arg) { // This is to validate a form if one of the top links is clicked and form has incomplete fields... if (ar
表单在MVC中使用Ajax.BeginForm构建
对于顶部的每个导航链接
元素,我都有一个JavaScript函数
var LoadTabs = function (e, arg) {
// This is to validate a form if one of the top links is clicked and form has incomplete fields...
if (arg !== "prev" && arg !== "next") {
if (!window.ValidateForm(false)) return false;
}
var url = $(this).attr('data'); // this contains link to a GET action method
if (typeof url != "undefined") {
$.ajax(url, { context: { param: arg } }).done(function (data) {
$('#partialViewContainer').html(data);
});
}
}
上面的函数绑定到页面加载时的每个顶部链接
$('.navLinks').on('click', LoadTabs);
我的“下一步”和“上一步”按钮基本上会触发单击事件,即LoadTabs
功能
$('button').on('click', function () {
if (this.id === "btnMoveToNextTab") {
if (!window.ValidateForm(true)) return false;
$.ajax({
url: url,
context: { param: 'next' },
method: "GET",
data: data,
success: function(response) {
if (typeof response == 'object') {
if (response.moveAhead) {
MoveNext();
}
} else {
$('#mainView').html(response);
}
ScrollUp(0);
}
});
}
if (this.id === "btnMoveToPreviousTab") {
MoveBack();
}
return false;
});
MoveNext() Implementation is as below:
function MoveNext() {
var listItem = $('#progressbarInd > .active').next('li');
listItem.find('.navLink').trigger('click', ['next']);
ScrollUp(0);
}
问题是,由于某些原因,当导航链接3处于活动状态时,我点击下一步按钮-而不是首先通过form.submit()发布表单-导航4被触发-因此,导航4的GET在导航3的表单发布之前运行
我的ValidateForm方法基本上只是检查表单是否存在并且有效,然后提交,否则返回false。详情如下:
function ValidateForm(submit) {
var form = $('form');
// if form doesn't exist on the page - return true and continue
if (typeof form[0] === "undefined") return true;
// now check for any validation errors
if (submit) {
if (!$(form).valid()) {
return false;
} else {
$(form).submit();
}
}
else {
return true;
}
return true;
}
我的推测是form.submit确实会被触发,但由于完成submit需要更长的时间,因此它会继续执行按钮onclick
事件中的下一个代码块
我首先认为这是C#的问题,因为在文章中,我用几个循环保存了一大块数据,任何处理量大的代码块我都参与其中
var saveTask = Task.Factory.StartNew(() => ControllerHelper.SomeMethod(db, model));
Task.WaitAll(saveTask);
WaitAll将等待并暂停执行,直到SomeMethod完成执行。我不确定如何用javascript锁定进程并等待它完成执行。因为我想如果我能在ValidateForm中锁定表单.submit(),直到它完成处理。。也许通过回调方法
如果有人能帮我找到正确的方向,我将非常感谢你的帮助。如果您需要更多信息,请让我知道我很乐意提供 编辑关于返回承诺的反模式
正如jfriend00所评论的,原始答案返回承诺的方式是反模式的,更好的方式是:
function ValidateForm(){
// do your logic
if (pass) {
return $.post("urlToPost");
else {
return $.Deferred().reject(xxx).promise();
}
}
更多信息,请结帐
原始答案
我将尝试想象您的问题:
您需要的是,首先在表单通过时运行ValidateForm
(例如,当表单发布完成时),然后执行MoveNext
您的问题是,MoveNext
在ValidateForm
完成之前被调用
如果我是正确的,那么原因是Javascript本质上是异步编程的,因此在完成某些操作时使用回调来触发
所以在你的情况下,你需要用承诺来实现它
基本上,您需要做的是:
让ValiateForm
返回承诺
仅在ValidateForm
完成后执行MoveNext
所以代码应该是这样的:
function ValiateForm(){
var dfd = jQuery.Deferred();
// do your logic
if(pass){
$.post("urlToPost"
} else {
// also failed
dfd.reject();
}
// return the promise
return dfd.promise();
}
然后你的“下一步”按钮会是
$('button').on('click', function () {
if (this.id === "btnMoveToNextTab") {
$.when(window.ValidateForm(true)).then(function(){
// after success post form
$.ajax({
url: url,
context: { param: 'next' },
method: "GET",
data: data,
success: function(response) {
if (typeof response == 'object') {
if (response.moveAhead) {
MoveNext();
}
} else {
$('#mainView').html(response);
}
ScrollUp(0);
}
});
if (this.id === "btnMoveToPreviousTab") {
MoveBack();
}
}
return false;
});
});
更多关于承诺结帐的信息
完成后跑步
编辑关于退货承诺的反模式
正如jfriend00所评论的,原始答案返回承诺的方式是反模式的,更好的方式是:
function ValidateForm(){
// do your logic
if (pass) {
return $.post("urlToPost");
else {
return $.Deferred().reject(xxx).promise();
}
}
更多信息,请结帐
原始答案
我将尝试想象您的问题:
您需要的是,首先在表单通过时运行ValidateForm
(例如,当表单发布完成时),然后执行MoveNext
您的问题是,MoveNext
在ValidateForm
完成之前被调用
如果我是正确的,那么原因是Javascript本质上是异步编程的,因此在完成某些操作时使用回调来触发
所以在你的情况下,你需要用承诺来实现它
基本上,您需要做的是:
让ValiateForm
返回承诺
仅在ValidateForm
完成后执行MoveNext
所以代码应该是这样的:
function ValiateForm(){
var dfd = jQuery.Deferred();
// do your logic
if(pass){
$.post("urlToPost"
} else {
// also failed
dfd.reject();
}
// return the promise
return dfd.promise();
}
然后你的“下一步”按钮会是
$('button').on('click', function () {
if (this.id === "btnMoveToNextTab") {
$.when(window.ValidateForm(true)).then(function(){
// after success post form
$.ajax({
url: url,
context: { param: 'next' },
method: "GET",
data: data,
success: function(response) {
if (typeof response == 'object') {
if (response.moveAhead) {
MoveNext();
}
} else {
$('#mainView').html(response);
}
ScrollUp(0);
}
});
if (this.id === "btnMoveToPreviousTab") {
MoveBack();
}
}
return false;
});
});
更多关于承诺结帐的信息
完成后跑步
我把这篇文章发给Alan,因为它是多行代码,我无法让它在评论中可读。为了避免有时运行异步操作,有时不运行异步操作时出现promise反模式,可以使用以下方法:
function ValidateForm(){
// do your logic
if (pass) {
return $.post("urlToPost");
else {
return $.Deferred().reject(xxx).promise();
}
}
这样,你总是回报一个承诺。在一个例子中,承诺来自$.ajax()
。在另一种情况下,您只是返回了一个被拒绝的承诺,因为操作已经失败。我将这篇文章发给Alan,因为它是多行代码,我无法让它在注释中可读。为了避免有时运行异步操作,有时不运行异步操作时出现promise反模式,可以使用以下方法:
function ValidateForm(){
// do your logic
if (pass) {
return $.post("urlToPost");
else {
return $.Deferred().reject(xxx).promise();
}
}
这样,你总是回报一个承诺。在一个例子中,承诺来自$.ajax()
。在另一种情况下,您只是返回一个被拒绝的承诺,因为操作已经失败。非常感谢@Alan-我会尝试一下,让您知道!再次感谢@Alan。我最终解决了所有问题,遇到了延迟实现的小问题,但它也得到了解决。谢谢快乐编码:)这里的第一个代码块是。由于$.post()
已经返回了一个承诺,因此不需要在它周围再包装一个承诺/延迟。您只需返回$.post()
已经返回的承诺,而无需创建自己的承诺。@jfriend00感谢您提供的信息。只是想进一步澄清一下最佳实践。因为OP提到它将验证表单和post-因此我的理解是它可能会在发布前失败客户端验证-因此承诺拒绝if(pass)
失败。因此,从$.post()
返回承诺是不可能的,因为它可能没有发生。在这种情况下,它仍然是反模式的吗?或者,有什么更好的方法来实现这一点?再次感谢您指出这一点,只是想确保在编辑我的答案供将来参考之前得到正确答案。我发布了一个避免这种反模式的方法,作为另一个答案。非常感谢@Alan-我会尝试一下,让您知道!再次感谢@Alan。我终于弄明白了一切,遇到了一个