javascriptjquerycallbackpromisejquery-callback

Binding a promise to a function


I've been trying to add a promise to a function so it would wait for the function to complete first. I've tried $.when, and .promise() as well as adding a counter and a variable which is changed when the .map function completes but I cannot get the checkInput() function to complete and change the values of x, inputSmartCheck, and inputTNACheck before the if statement executes. Because of this even when checkInput() changes the value of x to 1, the if statement executes before this happens and returns true. I have a little experience with Javascript (I prefer jQuery) but I think i'm venturing into advanced areas. Any help would be appreciated.

        $(document).on("click", ".updateNewRows", function(){
        $("#inputTNACheck").val("0");  //hidden inputs
        $("#inputSmartCheck").val("0"); //hidden inputs
        var x=0;
        checkInput();
        if(x==0 && $("#inputTNACheck").val()=="0" && $("#inputSmartCheck").val()=="0"){
            $(".newStart").each(function () {
                var get = $(this).closest(".newStart");
                var data = {
                    empID:get.find(".tna_id").val(),
                    smart:get.find(".smart_uname").val(),
                    first:get.find(".f_name").val(),
                    last:get.find(".l_name").val(),
                    date:get.find(".start_date").val(),
                    type:get.find(".type").val()
                };
                $.post('new_user_process_bulk_create_records.php', data, function(data,textStatus) {
                    console.log(textStatus);
                    $("#newUsersTable").remove();
                    $(".updateNewRows").remove();
                    if ($("#returnUsersTable").html()) {
                        $("#newUsersRow").html('<div class="alert alert-success">Updated</div>');
                    }
                    else{
                        location.reload();
                    }

                });
            });
        }   
    });



  function checkInput(){
        $('.newStart').map(function () {    

            var get = $(this).closest(".newStart");

            var id = get.find(".tna_id");
            var smart = get.find(".smart_uname");
            var first = get.find(".f_name");
            var last = get.find(".l_name");
            var type = get.find(".type");
            var smartCheck = $.ajax({
                url: "new_user_validate_bulk_upload.php",
                type: "POST",
                data: {smart:smart.val(), type:'smart'},
                success: function(data) {
                    if(data!="ok"){
                        $("#inputSmartCheck").val("1");
                        smart.css('background-color', 'pink');
                    }
                    else{smart.css('background-color', 'white');}
                }
            });

            var tnaCheck = $.ajax({
                url: "new_user_validate_bulk_upload.php",
                type: "POST",
                data: {tna:id.val(), type:'tna'},
                success: function(data) {
                    if(data!="ok"){
                        $("#inputTNACheck").val("1");
                        id.css('background-color', 'pink');
                    }
                    else{id.css('background-color', 'white');}
                }
            });
            $.when(smartCheck, tnaCheck).then(function() {  

                var name = new RegExp('^[a-zA-Z-]{0,20}$');
                var smartID = new RegExp('^[a-zA-Z0-9]{0,10}$');
                var empID = new RegExp('^[0-9]{0,10}$');

                if (!name.test(first.val()) || first.val()=='') {
                    x=1;
                    first.css('border', '1px solid red');
                }else{first.css('border', '1px solid #CCC');}

                if (!name.test(last.val()) || last.val()=='') {
                    x=1;
                    last.css('border', '1px solid red');
                }else{last.css('border', '1px solid #CCC');}

                if(!smartID.test(smart.val()) || smart.val()==''){
                    x=1;
                    smart.css('border', '1px solid red');
                }else{smart.css('border', '1px solid #CCC');}

                if(!empID.test(id.val()) || id.val()==''){
                    x=1;
                    id.css('border', '1px solid red');
                }else{id.css('border', '1px solid #CCC');}

                if(type.val()==''){
                    x=1;
                    type.css('border', '1px solid red');
                }else{type.css('border', '1px solid #CCC');}
            });//$.when close
        });
    }

Solution

  • Some basics first...

    I cannot get the checkInput() function to complete and change the values of x

    x is defined in your event handler, so when you reference it in checkInputs() even though it is called in your event handler, it does not have access do the variables that are defined in the scope of your event handler unless the checkInputs function were to also be defined in that event handler. (I wouldn't recommend that in this case, it would mean you're creating a function every time the event handler runs, not a big deal, but unnecessary nonetheless.)

    before the if statement executes

    Because checkInputs() does asynchronous things, you can not rely on simply calling it without some way to figure out if it's done. The good news is that you're on the right track with Promises.

    The way checkInputs currently works, you will never know if all the async stuff is done before your if statement. Let's work on that, with some example code based on your checkInputs function.

    function checkInputs() {
        // an array to store the async calls
        var asyncCalls = [];
    
        // iterate over all the things
        // changed to .each() because "each" is for iterating, 
        // and "map" is for returning a new array
        $('.newStart').each(function() {
            // get all your variables and stuff
            var smartCheck = $.ajax({...});
    
            var tnaCheck = $.ajax({...});
    
            var asyncCallsPromise = $.when(smartCheck, tnaCheck).then(function() {
                // do stuff
    
                console.log(arguments);
            });
            asyncCalls.push(asyncCallsPromise);
        });
    
        // the important part, return a promise so you can check 
        // when checkInputs has processed all the things
        return $.when.apply($, asyncCalls);
    }
    
    // somewhere else...
    checkInputs().then(function() {
      console.log('all the calls are done');
      // here you can do the things that need to happen after checking the inputs
      // e.g. the if statement.
    });
    

    Hope this little shove in the right direction helps