Search code examples
jqueryajaxauto-increment

Add incremented variable in jquery ajax success handler


I want to increment the value of a variable ii, but its value does not change. If I move ii++; before the alert function call, it increases but the value set to #spanstatus is always 0. How do I increment the value of ii, and still access it before my $.ajax call?

<html> 
      <span id="spanstatus"></span><br>

<script src="../js/jquery-1.12.4.min.js"></script>
<script>
var data = new FormData();
data.append('test', 'a');
data.append('test1', 'b');
data.append('test2', 'c');

function upload() {
        $('#spanstatus').html('');
        var ii=0;
        for(var [name, value] of data) {
            $('#spanstatus').append('<i>Uploading <b>"'+name+'"</b></i>...<span id="spanupload_'+ii+'">'+ii+'</span><br>');
                $.ajax({
                    type:'POST',
                    method: 'POST',
                    timeout:2000,
                    url:'upload.php?val='+value,
                    dataType: "json",
                    data:  value,
                    contentType: false,
                    cache: false,
                    processData:false,
                    // async: false,
                    success:function(response){
                            $('#spanupload_'+ii).html(ii+' OK');
                            alert(ii+'ok='+name);
                            ii++;
                    }
                });
        }
}

$(document).ready(function(){
    upload();
});

</script>
 </body> 
</html>

Solution

  • The success handler does not execute until the the response is received, which happens sometime later, as this is an asynchronous handler. This means the value of ii will not have changed when you make each call to $('#spanstatus').append.

    You could move the incrementing of ii so that it happens before the $('#spanstatus').append, but this introduces a new problem. In the success handler, ii will have been incremented once for each object in data, so it will always have the same value - in this case, 3 - when you call $('#spanupload_'+ii).html(ii+' OK').

    In order to keep a reference to each iteration within the for of loop, you must create a local, block-scoped variable with the value of ii at that iteration. You would need to do the same for name. The code would look like:

    var data = new FormData();
    data.append('test', 'a');
    data.append('test1', 'b');
    data.append('test2', 'c');
    
    function upload() {
      $('#spanstatus').html('');
      var ii = 0;
      for (var [name, value] of data) {
        ii += 1;
        const nextii = ii;
        const nextName = name;
    
        $('#spanstatus').append('<i>Uploading <b>"' + nextName + '"</b></i>...<span id="spanupload_' + nextii + '">' + nextii + '</span><br>');
        $.ajax({
          type: 'POST',
          method: 'POST',
          timeout: 2000,
          url: 'upload.php?val=' + value,
          dataType: "json",
          data: value,
          contentType: false,
          cache: false,
          processData: false,
          // async: false,
          success: function(response) {
            $('#spanupload_' + nextii).html(nextii + ' OK');
            alert(nextii + 'ok=' + nextName);
          }
        });
      }
    }
    
    $(document).ready(function() {
      upload();
    });
    

    I have created a fiddle for reference.