user3523426 user3523426 - 5 months ago 16
Javascript Question

How to pass cycle variable to event callback function using Javascript

I am uploading multiple files using XMLHttpRequest at the same time. I want each file to have its own progress indicator. So, when I get array of files for upload, I initiate upload for each of them inside a for cycle like

for(var i=0; i<files.length; i++)
{
// Create transfer object
var xhr = new XMLHttpRequest();

// Attach progress event handler
xhr.addEventListener('progress', function(e) { showProgress .... });

....
}


The issue is, how to pass correct "i" value to the progress callback function. In case I use "i" like this:

xhr.addEventListener('progress', function(e) { console.log(i); });


I always get the latest "i" value. In case define it like this:

xhr.addEventListener('progress', (function(i,e) { console.log(i); })(i));


I get correct I, but I never get the event object "e", so I don't get actual progress. What is correct way of defining it?

Answer

Use xhr.upload.progress instead of xhr.progress.

Create an IIFE, pass i to IIFE, create new progress element having className "progress-" with i concatenated, update current progress element .value to e.loaded within upload progress event. See also Upload multiple image using AJAX, PHP and jQuery

for(var i=0; i<files.length; i++) {
  // Create transfer object
  (function(curr) {
    // `i` : `curr`
    var xhr = new XMLHttpRequest();
    var progress = document.createElement("progress");
    progress.setAttribute("max", files[curr].size);
    document.body.appendChild(progress);
    progress.className = "progress-" + curr;
    // Attach progress event handler
    xhr.upload.addEventListener("progress", function(e) {
      // update current `progress` `value`
      document.querySelector(".progress-" + curr).value = e.loaded;
    });
    xhr.open("POST", "/path/to/server/");
    xhr.send(new FormData(files[curr]));
  }(i)); // pass `i` to IIFE
}

jsfiddle https://jsfiddle.net/ytedpcro/1/

Comments