简体   繁体   中英

Global Variable not affected in JQuery Ajax Success Function

I have a recursive function that populates a list until the bottom of the screen is reached, then stops.

Each time the recursive function is called, the "start" global variable increments by the limit (5). For example, after 3 times, the "start" variable should be 15. This shows up correctly in the console.

However, outside the recursive function, it seems the "start" variable is still at "0". I thought using "var start = 0" outside of the function makes it global and should be changed by the Ajax success function. The code is below:

//****************************************************************
//        Loading questions and answers listings
//****************************************************************
var tag = '';//initialize as blank
var search = '';//initialize as blank
var limit = 5;//number of records to autoload each time
var start = 0;//start at record 0
var action = 'inactive';//initial status to get initial load
var autoscroll = 'false';//check box to engage auto scroll or keep manual load more 
var checked = '';//check box value for autoscroll
function load_data(limit, start, search, tag){//recursive function for auto loading
    search = $('#search').val();
    var loads;
    $.ajax({
         url:"/modules/posts/questions_all_autoscroll_fetchdata.php",
         method:"POST",
         data:{limit:limit, start:start, search:search, tag:tag},
         cache:false,
         success:function(data){
            $('#load_data_message').show();//bring loading button back once load successful.  
            //It is removed during tag click search to avoid glitchy appearance of button showing at top left briefly.
            $('#load_data').append(data);
            //checks if quantity "limit" amount loaded.  If not, that means end of data reached.
            //Each data piece has id="container", so counting them tells how many data pieces returned in "loads"
            loads = $(data).find('.card-header').length;             
            if(loads<limit){button_name = 'End of Data';}else{button_name='Loading More &nbsp;&nbsp;<i class="fas fa-spinner fa-lg fa-spin"></i>';}
            if(autoscroll == 'false'){button_name = 'Load More'};
            //append data returned to bottom of existing data
            $('#load_data_message').html("<div id='please_wait' class='form-row text-center'>\
                  <div class='col-12'><button type='button' class='btn btn-warning'>\
                  "+button_name+"</button>\
                  <label style='cursor:pointer;'><input id='autoscroll' type='checkbox' name='autoscroll' value='true' "+checked+"\
                  style='transform:scale(2.0);margin-left:10px;margin-top:15px;cursor:pointer;'>&nbsp;&nbsp;Autoscroll</label><br></div></div>");
            action = "inactive";
            //recursive part - keep loading data until bottom of screen reached, stop when reached, or when end of data
            start = start + limit;
            console.log(start);
            if(loads>=limit){
                if($("#load_data").height() < $(window).height()){load_data(limit,start,search,tag);}
            }
        }
    });            
}

I do an initial load of the listing on page load with:

//for initial loading of data to the bottom of page (through recursive load_data function
if(action == 'inactive') {
    action = 'active';
    load_data(limit, start,search, tag);
 }  

Then if I want to initiate an auto/infinite scroll, I click the checkbox which initiates the code below. However, the "start" value is "0", where it should have been affected by the Ajax recursive function previously, and start at "15" instead. I get a repeat of previously posted data, which is not wanted.

//auto scroll checkbox clicked, putting into autoload/autoscroll mode
$(document).on("change", "#autoscroll", function(){
    autoscroll = this.checked;
    if(autoscroll == true){checked = 'checked';}else{checked = '';}
    console.log(start);
    load_data(limit, start, search, tag);
});

Then auto/infinite scroll works as follows. The "start" variable is continually updated successfully, but probably within the loop, rather than the recursive Ajax part.

//autoload portion.  when scrolling reaches bottom of screen, triggers another load of data      
$(window).scroll(function(){
    if(autoscroll == true){
        if($(window).scrollTop() + $(window).height() > $("#load_data").height() && action == 'inactive' && button_name != 'End of Data'){  
            action = 'active';
            start = start + limit;
            //load_data(limit, start, search, tag);
            setTimeout(function(){
             load_data(limit, start, search, tag);
            }, 500);
            console.log('scroll function called!');
        }
    }
});

Bottom line question - I would like to use the global variable "start" and have it changed by the recursive function's Ajax success function. How can this be achieved?

You have not mentioned what your 'data' response looks like in your ajax call. I tried a response string that looked like this:

<div class='card-header'>hello</div>
<div class='card-header'>world</div>
<div class='card-header'>foo</div>
<div class='card-header'>bar</div>
<div class='card-header'>howdy</div>

In this case, loads = $(data).find('.card-header').length does not provide a length of 5. If loads is only what you loaded in that specific ajax call, then you need $(data).length . Then, the console log for start in the ajax call gets incremented.

Note: Jquery $.find works on a DOM tree. $(data) returns an array of individual nodes, and $(data).length will return the pieces of data returned.

The "loads = $(data).find('.card-header').length" does count the number of class='card-header' instances, contrary to what user2137480 has mentioned above, and everything does increment properly. The issue was that the "start" variable outside the Ajax success function was not being updated as the "load_data" function was called recursively.

Found a clumsy way to make this work. I used a session storage variable, "sessionStorage.start" that gets affected within the Ajax success function, even at recursive levels. Seems like session variables scopes are truly "global"! Then this sessionStorage.start variable is use elsewhere in the code to update the global "start" variable. This value is then maintained consistently throughout the code. Just have to remember that the session variables are text and must be converted to numbers (for this application anyways). See below if you are interested:

//****************************************************************
//        Loading questions and answers listings
//****************************************************************
var limit = 5;//number of records to autoload each time
sessionStorage.start = 0;
var start = 0;//start at record 0
sessionStorage.start = start;
sessionStorage.scroll_function_enable = 'false';
var action = 'inactive';//initial status to get initial load
var autoscroll = 'false';//check box to engage auto scroll or keep manual load more 
var checked = '';//check box value for autoscroll
function load_data(limit, start, search, tag){//recursive function for auto loading
    console.log('load data begin');
    console.log('recursive start: ' + start);
    sessionStorage.scroll_function_enable = 'false';
    search = $('#search').val();            
    var loads;
    $.ajax({
         url:"/modules/posts/questions_all_autoscroll_fetchdata.php",
         method:"POST",
         data:{limit:limit, start:start, search:search, tag:tag},
         cache:false,
         success:function(data){
            $('#load_data_message').show();//bring loading button back once load successful.  
            //It is removed during tag click search to avoid glitchy appearance of button showing at top left briefly.
            $('#load_data').append(data);
            //checks if quantity "limit" amount loaded.  If not, that means end of data reached.
            //Each data piece has id="container", so counting them tells how many data pieces returned in "loads"
            loads = $(data).find('.card-header').length;   
            //alert(loads);
            if(loads<limit){button_name = 'End of Data';}else{button_name='Loading More &nbsp;&nbsp;<i class="fas fa-spinner fa-lg fa-spin"></i>';}
            if(autoscroll == 'false'){button_name = 'Load More'};
            //append data returned to bottom of existing data
            $('#load_data_message').html("<div id='please_wait' class='form-row text-center'>\
                  <div class='col-12'><button id='load_button' type='button' class='btn btn-warning'>\
                  "+button_name+"</button>\
                  <label style='cursor:pointer;'><input id='autoscroll' type='checkbox' name='autoscroll' value='true' "+checked+"\
                  style='transform:scale(2.0);margin-left:10px;margin-top:15px;cursor:pointer;'>&nbsp;&nbsp;Autoscroll</label><br></div></div>");
            action = "inactive";
            //recursive part - keep loading data until bottom of screen reached, stop when reached, or when end of data                    
            start = start + limit;
            sessionStorage.start = start;//needed because recursive routine does not update the global "start" variable.  Needed to pass value outside of recursive routine
            console.log('recursive end: '+start);
            if(loads>=limit){
                if($("#load_data").height() < $(window).height())
                {
                    load_data(limit,start,search,tag);
                }else
                    sessionStorage.scroll_function_enable = 'true';
                }
        }
    });  

}
//for initial loading of data to the bottom of page (through recursive load_data function
if(action == 'inactive') {
    action = 'active';
    load_data(limit, start,search, tag);
    start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value
 }  

//auto scroll checkbox clicked, putting into autoload/autoscroll mode
$(document).on("change", "#autoscroll", function(){
    autoscroll = this.checked;
    if(autoscroll == true){checked = 'checked';}else{checked = '';}
    start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value            
    console.log('autoscroll start: ' + start);
    load_data(limit, start, search, tag);
    start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value
});    

//autoload portion.  when scrolling reaches bottom of screen, triggers another load of data      

$(window).scroll(function(){
    if(autoscroll == true){
        if($(window).scrollTop() + $(window).height() > $("#load_data").height() && action == 'inactive' && button_name != 'End of Data' && sessionStorage.scroll_function_enable == 'true'){  
            action = 'active';
            start = Number(sessionStorage.start);//to get number where other processes have left off
            console.log('scroll start: ' + start);
            //load_data(limit, start, search, tag);
            setTimeout(function(){
             load_data(limit, start, search, tag);
            }, 500);
            start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value
        }
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM