javascript - How to keep a counter inside recursive AJAX call? -


this question has answer here:

i have rows of items. each row has different number of items. want counter keeps track of total number of items loaded. have function recursively loops through rows via ajax calls, (i have commented out stuff not relevant problem)

$(document).ready(function () {     var num_loaded = 0;     var row = 0;     load(row, num_loaded); }  function load(row, num_loaded) {     var count = num_loaded;     $.ajax({          // url , other stuff         // ...          success: function (response) {             (i = 0; < response.items.length; i++) {                  // load item[i]                  // ...                  count++;             }              // logic checks row+1 not out of bounds             // ...              load(row+1, count);         }      })      console.log(count); } 

as can see, upon success, each load function calls , pass in parameter keeps track of count. not work , keep getting nan or undefined in console. how accomplish , see final count of how many items loaded?

your main issue common 1 callbacks you're treating ajax synchronous call, when it's asynchronous. in other words, trying print count right after call ajax, count won't updated time.

var count = num_loaded; $.ajax({   // ... updates count time later }); // happens right after call $.ajax before success callback // count still has same value before called $.ajax console.log(count); 

here's related question can take at

additionally, you're defining counter inside load() method, means recreated on call stack each function call.

if pass count recursively through async callbacks, have correct value whenever recursion stops (i.e. reaches base case of maximum rows) must print inside callback:

$(document).ready(function () {   load(0, 0); }  function load(row, count) {    $.ajax({       // ...           success: function(response) {          // ... loop increments count          if ( /* base case reached */ ) {           console.log(count);         } else {           load(row + 1, count);         }       }     });   } } 

a cleaner , more reasonable approach use promises. can have load() method return promise on success either:

  • resolve promise loads next row, or
  • print count if base case reached.

since promises chainable, can pass count recursively:

function loadwithpromise(row, count) {   return new promise(function(resolve) {     $.ajax({       // ...           success: function(response) {          // ... loop increments count          // if reached base case, resolve promise (and whole chain)         if ( /* base case reached */ ) {           resolve(count);         }          // otherwise load next promise         else {           resolve(loadwithpromise(row + 1, count));         }       }     });   }); }  // recursively load rows , print count once we're done loadwithpromise(0, 0).then(function(count) {   console.log(count); }); 

if rows don't need loaded sequentially, can use promise.all wait calls load() finish before printing count. way can keep promises in array , let them happen independently, plus wouldn't need recursion. drawback though need have count defined globally since these promises unrelated:

var count = 0;  function loadwithpromise(row) {   return new promise(function(resolve) {     $.ajax({       // ...           success: function(response) {          // ... loop increments count          resolve();       }     });   }); }  var promises = []; (var row = 0; row < max_rows; row++) {   promises.push(loadwithpromise(row)); }  // once loading operations have resolved, print count promise.all(promises).then(function() {   console.log(count); }); 

Comments