等待form.submit()/ POST完成

时间:2017-03-25 01:30:54

标签: javascript c# jquery asp.net-mvc asp.net-mvc-5

我在这里遇到了一个非常奇怪的情况。解释起来很复杂,但我会尽我所能。

问题的详细说明:

  

在每个顶部导航点击(绿色甜甜圈/圆圈)或下一个按钮,我必须提交表格,如果它存在且有效。如果无效,form.valid()会触发验证错误,返回false会停止任何进一步的传播。这个设置完美无缺,直到我注意到一个不太持久的奇怪行为。特别是,我的第三个选项卡上的表单非常重要。当我点击下一个按钮时,它应该通过相同的过程:检查现有表格,如果有效,则提交。提交调用POST操作方法,当post完成时,获取下一个选项卡的视图。它的工作方式类似于5/10次,但在其他时候,GET在POST之前执行,这会导致下一页加载不完整的数据。当我将断点用于调试时,我看到GET用于在当前选项卡的POST之前执行的下一个选项卡。

用户界面说明:

我有一个顶部有4个导航<a>按钮的用户界面 - 中间有一个总是一个表单 - 而在底部我有以前的&amp;下一步按钮。

enter image description here

使用Ajax.BeginForm

在MVC中构建表单

对于顶部的每个导航链接<a>元素,我有一个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);

我的下一个&amp;以前的按钮基本上会触发点击事件,即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的POST。

我的ValidateForm方法基本上只是检查表单是否存在且有效然后是Submit,否则返回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确实会被触发,但由于提交需要更长的时间才能完成,因此继续使用按钮onclick事件中的下一个代码块。

我首先认为这是一个服务器方面的问题,因为在POST我用几个循环保存了一大块数据,并且任何代码块都是重要的,我有这个部分

var saveTask = Task.Factory.StartNew(() => ControllerHelper.SomeMethod(db, model)); Task.WaitAll(saveTask);

WaitAll将等待并暂停执行,直到SomeMethod完成执行。我不知道如何在JavaScript中锁定进程并等待它完成执行。因为我认为如果我可以以某种方式锁定ValidateForm中的form.submit()直到它完成处理..通过回调方法也许...

如果有人能指引我,我会非常感谢你的帮助。如果您需要更多信息,请告诉我,我很乐意提供!

1 个答案:

答案 0 :(得分:3)

Ajax是异步的,使用Ajax.BeginForm()的表单提交正在使用ajax。发生的事情是,当您点击“下一步”按钮时,会触发$('button').on('click', function () {代码:

  1. 您调用ValidateForm()函数(并假设其有效), 您的$(form).submit();代码行开始制作ajax POST
  2. 代码进展到ajax的最后return true;行 电话正在执行。
  3. 由于ValidateForm()函数返回true,$.ajax GET调用现在开始,但此时ajax POST在 ValidateForm()函数可能尚未完成执行导致 您的GET方法返回无效数据
  4. 您需要更改代码,以便在POST方法调用完成后进行GET调用。由于您在整个代码中使用$.ajax()方法,并且$.ajax()为您提供了更大的灵活性,因此似乎没有必要使用Ajax.BeginForm()(以及包含jquery.unbtrusive-ajax.js脚本的额外开销)。您还应该处理表单.submit()函数(如果您不希望“下一步”按钮成为表单中的提交按钮,您可以在按钮{{1]中触发.submit()事件处理程序)

    .click()

    您还应该考虑在$(document).on('submit', 'form', function(e) { e.preventDefault(); // cancel default submit var form = $(this); if (!form.valid()) { return; // will display the validation errors } .... // get the relevant urls to the GET and POST methods etc $.post(postUrl, form.serialize(), function(data) { .... // not clear if your [HttpPost] method returns anything }).done(function() { $.get(getUrl, someData, function(response) { .... // Update the DOM with the next form? .... // Re-parse the validator for client side validation } }).fail(function() { .... // code that you might run if the code in the [HttpPost] method fails }); }); 方法中返回相应的“下一个”视图,这样您就不需要再次回到服务器来获取它。

    还值得阅读Deferred Object documentation以及使用[HttpPost]$.when()等。