1

What I am attempting to accomplish here is to create a separate ajax request for each file being uploaded. I have an ajax call that creates a record and returns some html and the tempID of a record that is used by an ajax call which executes on success of the first call. This process appears to be functioning correctly. Where the problem is arising is the loop through the filesList. Before the ajax calls the loop appears to be working fine, but during the ajax call when I'm expecting the files list to increment to the next file in the array it is sending the first file again.

If I only select a single file then everything works correctly. It is as if the ajax calls do not see that the variable "file" is being reset at the beginning of the loop when there are multiple files....got me stumped...

/* Fire the ajax requests when the input files array changes
--------------------------------------------------------------------------*/
$('#theFile').on('change', function()
{
    var len = this.files.length;

    for(var i = 0; i < len; i++)
    {
        var file = this.files[i];
        // console.log(file.name); This shows the correct file name

        var formData = new FormData();
        formData.append("file_" + i, file);

        $.ajax(
        {
            url: '/controllerName/buildImageLoadingDIVS',
            type: 'POST',
            dataType:'json',
            data: 'fileName=' + file.name,
            success: function(data1)
            {
                $('#theImages').append(data1.content);

                formData.append("tempID", data1.tempID);

                // console.log(file.name); 
                // This shows the first filename in the array as if 
                // variable "file" was never set to new filelist

                $.ajax(
                {
                    url: '/controllerName/the_image_upload',
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    success: function(data2)
                    {
                        $('#temp_wrapper_' + data1.tempID).html(data2);
                    }
                });
            }
        });
    }
whitwhoa
  • 2,389
  • 4
  • 30
  • 61
  • Check [this](http://stackoverflow.com/questions/6077357/passing-index-from-for-loop-to-ajax-callback-function-javascript) question, that might be your problem – scumah May 18 '14 at 21:08

1 Answers1

2

You are facing closure problem. As all the success callback are sharing the same closure, so if any success callback is getting executed after the loop ends (which will be in most of the cases) all the success callback is sharing the same file value. Solution of this is creating a closure with IIFE.

Here is the modified code :

       //dummy file array    
        var fileArray = ['file1', 'file2', 'file3']
        var len = fileArray.length;

        for(var i = 0; i < len; i++)
        {
            var file = fileArray[i];
            console.log(file);

            var formData = new FormData();
            formData.append("file_" + i, file);
            (function(params){
                var file = params.file;
                var formData = params.formData;
                        $.ajax(
            {
                //used this url for testing purpose, replace it with yours
                url: 'http://fiddle.jshell.net',
                type: 'get',
                //change the datatype in your implementation
                dataType:'html',
                data: 'fileName=' + file,
                success: function(data1)
                {
                    //$('#theImages').append(data1.content);

                    formData.append("tempID", data1.tempID);

                    console.log("file name in success " + file); 


                    $.ajax(
                    {
                        url: 'http://fiddle.jshell.net',
                        type: 'get',
                        data: formData,
                        processData: false,
                        contentType: false,
                        success: function(data2)
                        {
                                            console.log("success"); 
                        }
                    });
                },
                error : function(){
                    console.log("error");
                }
            });
            })({
                'formData' : formData,
                'file' : file
            });
        }

You can find the fiddle here

MD. Sahib Bin Mahboob
  • 20,246
  • 2
  • 23
  • 45
  • +1 . Also, the AJAX calls may need to be sequentialised in some way. I'm not sure that you call X AJAX calls all together and that it would all work as expected. – Lee Taylor May 18 '14 at 21:49
  • you can easily do that by setting `async:true`. So no worry – MD. Sahib Bin Mahboob May 19 '14 at 06:09
  • I'd really avoid using `async:true` as this blocks the whole page and is a bit of kludge. – Lee Taylor May 19 '14 at 12:31
  • Right now it appears to be functioning correctly without setting async:true. Since the second ajax call happens on success of the first call should this not be safe (I only ask because I'm not certain). As far as being sequential I am not concerned if call executed by loop 4 finishes before call executed by loop 5 as each call will be uploading an image of variable size. If my logic is off please let me know. Thanks :) – whitwhoa May 19 '14 at 14:31