цикл через список файлов с помощью javascript

Здесь я пытаюсь создать отдельный запрос ajax для каждого загружаемого файла. У меня есть вызов ajax, который создает запись и возвращает некоторый html и tempID записи, которая используется вызовом ajax, который выполняется при успешном выполнении первого вызова. Этот процесс, кажется, работает правильно. Где возникает проблема, так это в цикле через filesList. Перед вызовами ajax цикл работает нормально, но во время вызова ajax, когда я ожидаю, что список файлов будет увеличиваться до следующего файла в массиве, он снова отправляет первый файл.

Если я выбираю только один файл, то все работает правильно. Это как если бы вызовы ajax не видели, что переменная «файл» сбрасывается в начале цикла, когда есть несколько файлов.... поставил меня в тупик...

/* 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);
                    }
                });
            }
        });
    }

person whitwhoa    schedule 18.05.2014    source источник
comment
Проверьте этот вопрос, который может быть вашим проблема   -  person scumah    schedule 19.05.2014


Ответы (1)


Вы столкнулись с проблемой закрытия. Поскольку все успешные обратные вызовы используют одно и то же закрытие, поэтому, если какой-либо успешный обратный вызов выполняется после завершения цикла (что будет в большинстве случаев), все успешные обратные вызовы используют одно и то же значение файла. Решением этого является создание замыкания с помощью IIFE.

Вот измененный код:

       //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
            });
        }

Вы можете найти скрипт здесь

person MD. Sahib Bin Mahboob    schedule 18.05.2014
comment
+1 . Кроме того, вызовы AJAX могут нуждаться в некоторой последовательности. Я не уверен, что вы вызываете вызовы X AJAX все вместе и что все это будет работать так, как ожидалось. - person Lee Taylor; 19.05.2014
comment
вы можете легко сделать это, установив async:true. Так что не беспокойтесь - person MD. Sahib Bin Mahboob; 19.05.2014
comment
Я бы действительно избегал использования async:true, так как это блокирует всю страницу и немного мешает. - person Lee Taylor; 19.05.2014
comment
Сейчас он работает правильно без установки async: true. Поскольку второй вызов ajax происходит при успехе первого вызова, это не должно быть безопасно (я спрашиваю только потому, что не уверен). Что касается последовательности, меня не беспокоит, завершается ли вызов, выполняемый циклом 4, до вызова, выполняемого циклом 5, поскольку каждый вызов будет загружать изображение переменного размера. Если моя логика отключена, пожалуйста, дайте мне знать. Спасибо :) - person whitwhoa; 19.05.2014