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();which を呼び出します

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 の Deferred (および promise) を使用すると、簡単なコードを記述できますが、Deferred を最初に使用すると、最初は、少なくともほんのわずかですが、頭がおかしくなる傾向があります。

このような問題に対して Deferred を使用する唯一の方法はありませんが、ここではその 1 つを示します。

$(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()ajax が含まれているかどうかに応じて、valUsr()またはと同じ形式になります。samePwd()

于 2012-10-18T02:42:28.073 に答える
1

Ajaxはオンザフライで同期的に実行されます

成功コールバックでajaxリクエストが完了した、他のフィールドの検証を確認する必要があります。同期リクエストをオフにすることはできますが、ブラウザは同期リクエストを取得するまでフリーズします。

これを反映するために、呼び出しを再構築する必要があります。パスワードの入力が完了し、フィールドがぼやけたらすぐに、確認のリクエストを送信することをお勧めします。そうすれば、エラーが発生した場合に、フォームの最後で待機時間を防ぐことができます。

于 2012-10-17T22:51:22.453 に答える