javascript - 等待 form.submit()/POST 完成

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

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

问题的详细解释:

On every top Nav click (Green donuts/circles), or next button, I must submit the form, if it exists and is valid. If not valid, form.valid() triggers validation errors and return false would stop any further propagation. This setup was working flawlessly until I noticed a strange behavior which isn't very persistence. Form on my 3rd tab, specifically, is quite data heavy. When I hit next button it should practically go thru the same process: check for an existing form, if valid, then submit. Submit calls the POST action method and when post completes it GETs the view for next tab. It works like this 5/10 times but at other times GET executes before the POST, which causes next page to load with incomplete data. When I put breakpoints to debug, I see GET for the next tab executing before POST of the current tab.

UI 解释:

我有一个带有 4 个导航的 UI <a>按钮在顶部 - 在中心总是有一个表单 - 在底部我有上一个和下一个按钮。

enter image description here

表单是在 MVC 中使用 Ajax.BeginForm 构造的

对于每个导航链接 <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);
        });
    }
}

上面的这个函数绑定(bind)到页面加载时的每个顶部链接。

$('.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);
}

问题是,由于某些原因,当 Nav Link 3 处于事件状态并且我点击 NEXT 按钮时 - 而不是首先通过 form.submit() 发布表单 - 导航 4 被触发 - 因此导航 4 的 GET 在表单之前运行导航 3 的 POST。

我的 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 确实被触发了,但由于提交需要更长的时间才能完成,因此它继续按钮中的下一个代码块 onclick事件。

我首先认为这是一个服务器端问题,因为在 POST 中我用几个循环保存了大量数据,任何处理繁重的代码块我都有这部分

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

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

如果有人能指导我正确的方向,我将不胜感激。如果您需要更多信息,请告诉我,我很乐意提供!

最佳答案

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

  1. 您调用 ValidateForm() 函数(并假设其有效), 您的 $(form).submit(); 代码行开始生成 ajax POST
  2. 代码进行到最后的 return true; 行,而 ajax 调用正在执行。
  3. 因为 ValidateForm() 函数返回 true,$.ajax GET 调用现在开始,但此时 ajax POST 在 ValidateForm() 函数可能没有完成执行导致 您的 GET 方法返回无效数据

您需要更改代码,以便在 POST 方法调用完成后进行 GET 调用。由于您在整个代码中使用了 $.ajax() 方法,并且 $.ajax() 为您提供了更大的灵 active ,因此似乎没有必要使用 Ajax。 BeginForm()(以及包含 jquery.unbtrusive-ajax.js 脚本的额外开销)。您还应该处理表单 .submit() 函数(如果您不希望“下一步”按钮成为表单中的提交按钮,您可以触发 .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
    });
});

您还应该考虑在 [HttpPost] 方法中返回适当的“下一个” View ,这样您就不需要再次调用服务器来获取它。

Deferred Object documentation 也值得一读以及$.when()$.then()等的使用

关于javascript - 等待 form.submit()/POST 完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43011545/

相关文章:

javascript - 是否可以阻止浏览器解析某些元素?

javascript - 3维数组在javascript中拆分

javascript - DataTable 获取tr的数据

javascript - jQuery addClass 不适用于动态更改的输入

javascript - 错误: $injector:modulerr Module Error/Angular service

javascript - mouseleave() 不删除类

c# - 无法加载文件或程序集 'Microsoft.AspNet.TelemetryCorrelation' 或其依赖项之一。该系统找不到指定的文件

C#的LINQ和.NET Framework,哪个依赖?

c# - 什么是 "naturally asynchronous"或 "pure asynchronous"?

javascript - 如何将事件 stopPropagation 限制为祖先元素?