JQuery: Return $.get() callback to outer scope

2019-01-29 09:26发布

问题:

I'm working on this validation script for my latest project, and one of the requirements is that it checks if the value that the user enters is in the database, and if it isn't it returns an error.

function validateSteps(){
    var FormErrors = false;
    for(var i = 1; i < fieldsetCount; ++i){
        var error = validateStep(i);
        if(error == -1)
            FormErrors = true;
    }
    $('#formElem').data('errors',FormErrors);   
}

function validateStep(step){
    if(step == fieldsetCount) return;

    var error = 1;
    var hasError = false;
    $('#formElem').children(':nth-child('+ parseInt(step) +')').find(':input:not(button)').each(function(){
        var $this       = $(this);
        var valueLength = jQuery.trim($this.val()).length;
        var inputValue = jQuery.trim($this.val());
        var errorID = $this.attr('name') + "_err";
        var errorPrepend = "<div class='rf_error' id='" + errorID +"'>";
        var errorAppend = "</div>";
        var errorMsg = "";

        /* =================================
         MORE VALIDATION STATEMENTS HERE
         ============================ */

        if($this.is('.rf_GrpCode') && !hasError)
        {
            $.get("inc/scripts/formHandle.php", { GrpCode: inputValue, type: "groupCode" }, function(data) {
                if(!data.GrpCode)
                {
                    hasError = true;
                    errorMsg = "The code you have entered is invalid.";

                }
            }, "json");
        }

        if(hasError)
        {
            $this.css('background-color','#FFEDEF');
            //alert("Has error: " + errorID);
            if(errorMsg)
            {

                if($('#' + errorID).length)
                {
                    $('#' + errorID).html(errorMsg);
                }
                else
                {
                    $this.after(errorPrepend + errorMsg + errorAppend);
                }
            }
        }
        else
        {
            //alert("Has no error: " + errorID);
            $('#' + errorID).remove();
            $this.css('background-color','#FFFFFF');    
        }
    });

   var $link = $('#navigation li:nth-child(' + parseInt(step) + ') a');
    $link.parent().find('.error,.checked').remove();

    var valclass = 'checked';
    if(hasError){
        error = -1;
        valclass = 'error';
    }
    $('<span class="'+valclass+'"></span>').insertAfter($link);

    return error;
}

$('#registerButton').bind('click',function(){
    if($('#formElem').data('errors')){
        $.confirm({
            'title'     : 'Ooops!',
            'message'   : 'It appears some of the information you have entered is invalid. Please go back through the steps a amend the marked fields.',
            'buttons'   : {
                'OK'    : {
                    'class' : 'blue',
                    'action': function(){}
                }
            }
        });
        return false;
    }   
});

The $.get() request itself works fine and will get through into the if statement if there is no instance of the value in the database. However once it comes to the error handling section it's not picking up the variables that I set within the if statement.

I can understand why it's not working, because those variables are being set out of the scope of the rest of the function. Unfortunately this is as far as my knowledge goes, and am at a loss as to how to get those variables to be recognised by the error handeling section at the end.

Hope that makes sense,

Any help is greatly appreciated, thanks,

Lyndon

回答1:

The issue is that get is simply a shortcut for doing an AJAX get request. AJAX is asynchronous, so the request is returning after you've checked the variable. You have a few options here. Normally I don't encourage blocking on an ajax call (kind of defeats the purpose), but if this is happening on submit, then it may make sense.

You can change get to ajax and set async: false. This will wait for the request to finish before moving on.

If you have multiple such calls that you need to wait for, you should have a look at http://api.jquery.com/jQuery.when/ , this will allow the requests to run in parallel, but still wait for all to complete before moving on.



回答2:

The $.get() request is asynchronous. You will only have hasError set after the response comes in, which is a lot later than when you're checking it.



回答3:

The problem is, that your ajax call is asynchron. So your condition check if(hasError) { will be executed before your success handler even set the value for hasError. You can't execute code directly after you initiated your ajax call. Instead have all other code within your success listener.

if($this.is('.rf_GrpCode') && !hasError)
{
    $.get("inc/scripts/formHandle.php", { GrpCode: inputValue, type: "groupCode" }, function(data) {
        if(!data.GrpCode)
        {
            errorMsg = "The code you have entered is invalid.";


            $this.css('background-color','#FFEDEF');
            //alert("Has error: " + errorID);
            if(errorMsg)
            {

                if($('#' + errorID).length)
                {
                    $('#' + errorID).html(errorMsg);
                }
                else
                {
                    $this.after(errorPrepend + errorMsg + errorAppend);
                }
            }
        }
        else
        {
            //alert("Has no error: " + errorID);
            $('#' + errorID).remove();
            $this.css('background-color','#FFFFFF');    
        }
    }, "json");
}


回答4:

The get function is asynchronous. You process the results probably before an answer has arrived.