替代AJAX async:表单提交按钮单击事件处理程序的false选项

时间:2015-10-05 12:52:54

标签: javascript jquery ajax asynchronous

我有一个登录表单,我们对服务器进行AJAX调用,以便在让登录表单继续提交之前执行一些验证。目前的代码概述如下:

(function ($) {
    var errorMessageHtml = "";
    function isUserValid(username) {
        if (username.length <= 0) {
            return false;
        }
        var userIsValid = false;
        $.ajax({
            async: false,
            url: "/myAjaxCall?username=" + username
        }).success(function (validationResult) {
            userIsValid = validationResult.IsValid;
            errorMessageHtml = validationResult.ErrorMessage;
        }).fail(function () {
            errorMessageHtml = "Error contacting server. Please try again.";
        });

        return userIsValid;
    }

    var $usernameTextbox = $("#UserName");
    var $errorMessageLabel = $(".errorMessageContainer");

    $(".loginButton").on("click", function (e) {
        $errorMessageLabel.hide();
        if (isUserValid($usernameTextbox.val())) {
            return true;
        } else {
            $errorMessageLabel.show();
            $errorMessageLabel.html(errorMessageHtml);
        }
        e.preventDefault();
        return false;
    });
})(jQuery);

我知道async: false是不应该被使用的东西,因为它已经过时了。我的问题是:替代方案是什么。我的click事件处理程序需要返回true或false,这意味着它必须等待ajax调用完成。如果async: false不再是一个选项,那么isUserValid方法将立即返回,而不会正确设置userIsValid布尔值。

现在我可以将ajax方法调用直接内联到$(".loginButton")上调用的click事件处理程序,但同样的问题出现了:它需要返回true或者防止默认(即阻止login)并返回false,具体取决于ajax调用的结果。有没有办法可以强制click事件处理程序在返回之前等待ajax调用的结果,而不使用async: false?我知道有一个jQuery when()方法,但我不知道在这种情况下是否可以使用它。

2 个答案:

答案 0 :(得分:3)

首先,可以在不单击相应提交按钮的情况下提交form。因此,将submit事件绑定到form。现在,根据ajax请求结果,您可以使用例如

提交form
(function ($) {
    var errorMessageHtml = "";
    function isUserValid(username) {
        $errorMessageLabel.hide();
        if (username.length <= 0) {
            return false;
        }
        var userIsValid = false;
        // return the promise from ajax method
        return $.ajax({            
            url: "/myAjaxCall?username=" + username
        }).success(function (validationResult) {
            userIsValid = validationResult.IsValid;
            errorMessageHtml = validationResult.ErrorMessage;
        }).fail(function () {
            errorMessageHtml = "Error contacting server. Please try again.";
        });
    }

    var $usernameTextbox = $("#UserName");
    var $errorMessageLabel = $(".errorMessageContainer");
    // "form:has(.loginButton)" or whatever more relevant selector
    $("form:has(.loginButton)").on("submit", function (e) {
        $errorMessageLabel.hide();
        isUserValid($usernameTextbox.val())).always(function(validationResult ){
            if(validationResult && validationResult.IsValid) {
                this.submit();
            } else {
                $errorMessageLabel.html(errorMessageHtml).show();
            }
        }.bind(this));            

        e.preventDefault();
    });
})(jQuery);

答案 1 :(得分:0)

A. Wolff's answer是我接受的答案,但我想根据他们的输入以及来回做出的各种评论来分享我的最终代码解决方案。

(function ($) {
    "use strict";

    var $usernameTextbox = $("#UserName");
    var $passwordTextbox = $("#Password");
    var $errorMessageLabel = $(".errorMessageContainer");

    $("form").on("submit", function (e) {
        $errorMessageLabel.hide();
        var username = $usernameTextbox.val();
        if (username.length <= 0 || $passwordTextbox.val().length <= 0) {
            return; // Server posts back with "username/password required" so we don't handle it here.
        }

        $.get("/myAjaxCall?username=" + username).done(function (validationResult) {
            if (validationResult.IsValid) {
                this.submit();
            } else {
                $errorMessageLabel.html(validationResult.ErrorMessage).show();
            }
        }.bind(this)).fail(function() {
            $errorMessageLabel.html("Error contacting server. Please try again.").show();
        });            

        e.preventDefault();
    });
})(jQuery);