0

我有一个功能可以在按下按钮时验证某些字段。第一个检查用户名和密码是否真实。然后如果密码是适当安全的。然后,如果它与确认密码框匹配。但是,在第一个函数中的警报弹出之前,检查用户是否真实的 ajax 似乎没有完成。

$(document).ready(function() {
    $('#submit_pw_ch').on('click', function(){

        var alertString = "Please correct the following errors: \n"
        //current username and password are correct
        var vUsr = valUsr();
        //new password is sufficiently secure
        var vPwd = valPwd();
        //confirmation of new password is same as previous box
        var sPwd = samePwd();

        console.log('valid user : ' + vUsr + '      valid password : ' + vPwd + '     same password : ' + sPwd);

        //append appropriate warnings to alert string
        if ( !vUsr ) { alertString += "-Your current username and password are invalid. \n"; }
        if ( !vPwd ) { alertString += "-The new password you have selected is not strong enough. \n"; }
        if ( !sPwd ) { alertString += "-The confirmation of your new password does not match the previous entry. \n"; }


        if ( !vUsr || !vPwd || !sPwd ) {
            alert(alertString);
            return false;
        } else {

            //change password

        }

    });
});

所以检查的那一行是var vUsr = valUsr();调用

function valUsr() {

    var un = $('#uNameInput').val();
    var pw = $('#uPwdInput').val();
    //return value
    var validUsr = false;

    $.ajax({
        type: "post",
        url: "queries/confirm_user.php?<?=time()?>",
        data: "un=" + un + "&pw=" + pw,
        dataType: "json",
        success: function (returnedData) {
            console.log(returnedData)
            if (data == 'true') {
                validUsr = true;
            } else {
                validUsr = false;
            }
        } 

    });

    return validUsr;
}

不知何故,虽然警报没有等待 ajax 完成获取它的数据。console.log(returnedData)关闭警报框后,该功能valUsr()会出现在控制台中。为什么会这样?我该如何预防?谢谢!

4

2 回答 2

2

托马斯,

您需要满足 ajax 固有的异步性,换句话说,您需要等到对 ajax 请求的响应到达后再决定要做什么。

jQuery 的 Deferreds(和 Promise)允许我们编写简单的代码,但 Deferreds 一开始往往会让你大吃一惊,至少是非常轻微的。

没有独特的方法可以使用 Deferreds 来解决这样的问题,但这里有一个。

$(document).ready(function() {
    $('#submit_pw_ch').on('click', function() {
        var form = this.form; //the form containing the submit button and the fields .

        //`alertArr` is an array to which messages will be added.
        var alertArr = ["Please correct the following errors:"];

        //`addAlert` will be called from a `Deferred.resolveWith(this, ...)` statement.
        //The context, `this`, is unused.
        function addAlert(index, txt) {
            alertArr[index] = txt;
        }

        //`compositeAction` will be called from a promise.done() statement.
        function compositeAction() {
            //first filter out null messages (ie. validation successes) from alertArr.
            var message = $.map(alertArr, function(txt, i){
                return txt || null;
            });
            if(message.length > 1) {
                //then alert the complete message with line breaks
                alert(message.join("\n"));
            } else {
                //submit the form to change the password
                //or another ajax call as required
                form.submit();
            }
        }

        // Invoke ajax validators and assign returned promises.
        // An index is passed, so the text messages can be displayed in a logical order, 
        // regardless of the order in which the validation promises are resolved.
        //If we didn't care about the order of the messages then the code would be slighly simpler.
        var vUsr = valUsr(0),
            vPwd = valPwd(1),
            sPwd = samePwd(2);

        //All validations adopt a similar pattern regardless of whether ajax is involved or not.
        //Here, we establish what is to be done when the promise are resolved, or
        //what is to be done immediately if the promise are alrady resolved.
        vUsr.done(addAlert);
        vPwd.done(addAlert);
        sPwd.done(addAlert);
        //At this stage, `addAlert` will contain entries for successful as well as unsuccessful validations. Successful entries will be filtered out by `compositeAction`

        //Establish what is to be done when all three promises are resolved.
        $.when(vUsr, vPwd, sPwd).done(compositeAction);

        //Return false unconditionally
        return false;
    });

    function valUsr(index) {
        var messages = {
            validated: '',//important - this message must be an empty string - do not change
            notValidated: '- Your current username and password are invalid.',
            ajaxError: '- Validation error: username and password.'
        };

        //Create a Deferred object, which will be resolved in response to several different outcomes.
        var def = $.Deferred();

        $.ajax({
            type: "post",
            url: "queries/confirm_user.php?<?=time()?>",
            data: {
                'un': $('#uNameInput').val(),
                'pw': $('#uPwdInput').val()
            },
            dataType: "json",
            success: function (returnedData) {
                if (returnedData == 'true') {
                    def.resolveWith(this, [index, messages.validated]);
                } else {
                    def.resolveWith(this, [index, messages.notValidated]);
                }
            },
            error: function() {
                def.resolveWith(this, [index, messages.ajaxError]);
            }
        });
        return def.promise();//Return a promise derived from the as yet unresolved Deferred.
    }

    function samePwd(index) {
        var pw1 = $('#uPwdInput').val();
        var pw2 = $('#uPwdInput2').val();
        var errMessage = (pw1 === pw2) ? '' : '-The confirmation of your new password does not match the previous entry';
        var def = $.Deferred();//Create a Deferred object, which will be resolved immediately
        def.resolveWith(this, [index, errMessage]);
        return def.promise();//Return a promise derived from the already resolved Deferred.
    }
});

valPwd()将与valUsr()or具有相同的格式samePwd(),具体取决于是否涉及 ajax。

于 2012-10-18T02:42:28.073 回答
1

Ajax 实时运行,同步运行

在成功回调中完成 ajax 请求,您需要检查其他字段的验证。您可以关闭同步请求,但浏览器将冻结,直到它得到一个,不建议。

您将需要重组您的电话以反映这一点;我建议他们在输入完密码并且字段模糊后立即发送检查请求。这样,如果有任何错误,您将能够避免在表单末尾等待时间。

于 2012-10-17T22:51:22.453 回答