等待form.submit()/POST完成 [英] Wait for form.submit() / POST to complete

查看:579
本文介绍了等待form.submit()/POST完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被困在一个非常奇怪的情况下.解释起来很复杂,但我会尽力而为.

I'm stuck in a really bizarre situation here. It's complicated to explain but I'll try my best.

问题的详细说明:

在每一次Nav导航单击(绿色甜甜圈/圆圈)或下一个按钮上,如果表单存在且有效,我都必须提交该表单.如果无效,form.valid()将触发验证错误,返回false将停止任何进一步的传播.在我发现一个奇怪的行为(不是很持久)之前,该设置可以完美地工作.特别是在我的第三个标签上,表格的数据量很大.当我按下下一步"按钮时,它实际上应该经过相同的过程:检查现有表格(如果有效),然后提交.提交调用POST操作方法,并在发布完成后获取下一个选项卡的视图.它像这样运行5/10次,但其他时候GET在POST之前执行,这会导致下一页加载不完整的数据.当我放置断点进行调试时,我看到下一个选项卡的GET执行在当前选项卡的POST之前.

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个导航<a>按钮-中间总是有一个表单-底部有Previous&下一步按钮.

I have a UI with 4 navigation <a> buttons on top - in the center there's a always a form - and at the bottom I have Previous & Next buttons.

使用Ajax.BeginForm

对于顶部的每个Nav链接<a>元素,我都有一个JavaScript函数

For each Nav link <a> element on top, I have a JavaScript function

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);
        });
    }
}

上面的函数绑定到页面加载时的每个顶部链接.

This function above binds to each top link on page load.

$('.navLinks').on('click', LoadTabs);

我的下一个&以前的按钮基本上会触发点击事件,即LoadTabs功能.

My Next & Previous buttons basically trigger the click event i.e. LoadTabs function.

$('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在表单之前运行Nav 3的发布.

The problem is, for some reasons, when Nav Link 3 is active and I hit NEXT button - Instead of posting the form first via form.submit() - the nav 4 gets triggered - hence GET for nav 4 runs before form POST of nav 3.

我的ValidateForm方法基本上只是检查表单是否存在并且有效,然后提交,否则返回false.如下:

My ValidateForm method is basically just checking if the form exists and is valid then Submit, else returns false. Its as below:

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事件中的下一个代码块.

My speculation is that form.submit does get triggered as it should be but since submit takes a little longer to finish it continues with the next code block in the button onclick event.

我首先认为这是服务器端的问题,因为在POST中,我通过一些循环保存了大量数据,而任何处理繁重的代码块我都在其中

I first thought that this is a server side issue as in the POST I'm saving a big chunk of data with a few loops, and any code block that's process heavy I have that part in

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

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

WaitAll will wait and pause the execution until SomeMethod finishes executing. I'm not sure how can I lock a process in JavaScript and wait for it to finish execution. Because I think If i can somehow lock the form.submit() in ValidateForm until its finished processing .. via a callback method perhaps...

请任何人朝正确的方向前进,我将非常感谢您的帮助.如果您需要更多信息,请告诉我,我们很乐意提供!

Please if anyone can put me in right direction, I'd greatly appreciate the help. If you need more information please let me know I'd be happy to provide!

推荐答案

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

Ajax is async, and your forms submit which is using Ajax.BeginForm() is using ajax. What is happening is that when you click your 'Next' button, which triggers the $('button').on('click', function () { code:

  1. 您调用ValidateForm()函数(并假设其有效), 您的$(form).submit();代码行开始进行ajax POST
  2. 在ajax期间,代码将前进到最后的return true;行 呼叫正在执行.
  3. 由于ValidateForm()函数返回true,因此$.ajax GET调用现在开始,但此时Ajax POST在 ValidateForm()函数可能尚未完成执行,导致 您的GET方法以返回无效数据
  1. You call the ValidateForm() function (and assuming its valid), your $(form).submit(); line of code starts making a ajax POST
  2. The code progresses to the final return true; line while the ajax call is executing.
  3. Because the ValidateForm() function returned true, the $.ajax GET call now starts, but at that point the ajax POST in the ValidateForm() function may not have finished executing causing your GET method to return invalid data

您需要更改代码,以便在POST方法调用完成后进行GET调用.而且,由于在整个代码中都使用了$.ajax()方法,而$.ajax()为您提供了更大的灵活性,因此似乎没有必要使用Ajax.BeginForm()(以及包括jquery.unbtrusive-ajax.js脚本的额外开销).您还应该处理表单.submit()函数(如果您不希望下一步"按钮成为表单中的提交按钮,则可以在按钮.click()处理程序中触发.submit()事件)

You need to change your code so that the GET call is made once the POST method call has completed. And since your using the $.ajax() methods throughout your code, and $.ajax() gives you more flexibility, it seems unnecessary to use Ajax.BeginForm() (and the extra overhead of including the jquery.unbtrusive-ajax.js script). You should also be handling the forms .submit() function (if you do not want the 'Next' button to be a submit button in the form, you could just trigger the .submit() event in the buttons .click() handler)

$(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]方法中返回适当的下一个"视图,这样您就无需再次调用服务器来获取它了.

You should also consider returning the appropriate 'next' view in the [HttpPost] method so that you don't then needs to make a second call back to the server to get it.

也值得阅读延迟对象文档$.then()

这篇关于等待form.submit()/POST完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆