0

我正在尝试为我的博客系统制作一个文件上传器,它只会让用户将文件放入其中,然后它会自动将它们上传到服务器。奇怪的是(对我来说),console.log在它被填充之前输出 dataArray ,而在超时后调用它会正确输出它。

例如,如果我在放置区放置 4 个文件,我会得到:

[]
[file1, file2, file3, file4]

然后我在不上传/刷新的情况下再删除 4 个文件,我得到:

[file1, file2, file3, file4]
[file1, file2, file3, file4, file5, file6, file7, file8]

所以我的脚本由于某种原因异步工作?有人可以告诉我我在这里做错了什么吗?

var dataArray    = [];

$('.dropArea').bind(
{
    drop: function(e)
    {
        e.stopPropagation();
        e.preventDefault();
        var files = e.dataTransfer.files;

        $.each(files, function(index, file)
        {
            var fileReader = new FileReader();

            fileReader.onload = (function(file)
            {
                return function(e)
                {
                    var image = this.result;

                    dataArray.push({
                        name : file.name,
                        value: image
                    });
                }
            })(files[index]);

            fileReader.readAsDataURL(file);
        });

                    console.log(dataArray);
        setTimeout(function() { console.log(dataArray) }, 1000);
    },
});
4

2 回答 2

1

你应该console.log()在回调中。

fileReader.onload = (function(file)
{
    return function(e)
    {
        var image = this.result;

        dataArray.push({
            name : file.name,
            value: image
        });

        console.log(dataArray);
    }
})(files[index]);

如果您在回调之外调用它,它将在图像开始加载后立即运行,而不是在图像完成加载时运行。

我已经快速绘制了一张图片以进行澄清:

描述

您可以通过比较丢弃的图像数量和完成加载的图像数量来解决此问题,如下所示:

var dataArray    = [];
var count = 0; // amount of files dropped
var ready = 0; // amount of files finished loading

$('.dropArea').bind(
{
    drop: function(e)
    {
        ...

        $.each(files, function(index, file)
        {
            count++; // we start handling a file here so we increment

            ...

            fileReader.onload = (function(file)
            {
                return function(e)
                {
                    ...

                    ready++; // this image has finished loading so we increment
                }
            })(files[index]);
        });

        setTimeout(function() {
            if(ready === count) {
                // all images have been loaded
                console.log(dataArray);
            }
        }, 1000);
    },
});
于 2013-01-03T08:39:14.347 回答
0

正如@Tim S. 回答的那样,文件开始加载时会触发 onload 事件,并且可能需要一些时间,具体取决于文件大小。以下是我如何解决发现是否所有文件都已加载的问题。

drop: function(e)
    {
        e.stopPropagation();
        e.preventDefault();
        var files = e.dataTransfer.files;
        console.log(files.length + " queued for upload");

        var counter = 0;
        var loaded = 0;
        $.each(files, function(index, file)
        {
            counter++;
            console.log("File #"+counter+" loading started.")
            if (!files[index].type.match('image.*'))
            {
                $('.dropArea').html(message.error.onlyImage);
                errorMessage++;
            }
            var fileReader = new FileReader();

            fileReader.onload = (function(file, count)
            {
                return function(e)
                {
                    var image = this.result;

                    dataArray.push({
                        name : file.name,
                        value: image
                    });

                    loaded++;
                    console.log("File #"+count+" loaded.");

                    if (loaded == files.length) {
                        console.log("Loading finished!");
                    }
                }
            })(files[index], counter);

            fileReader.readAsDataURL(file);
        });
    }

实际上,控制台日志输出如下所示:

4 queued for upload 9a840a0_part_2_dragndrop_2.js:25
File #1 loading started. 9a840a0_part_2_dragndrop_2.js:32
File #2 loading started. 9a840a0_part_2_dragndrop_2.js:32
File #3 loading started. 9a840a0_part_2_dragndrop_2.js:32
File #4 loading started. 9a840a0_part_2_dragndrop_2.js:32
File #2 loaded. 9a840a0_part_2_dragndrop_2.js:52
File #4 loaded. 9a840a0_part_2_dragndrop_2.js:52
File #3 loaded. 9a840a0_part_2_dragndrop_2.js:52
File #1 loaded. 9a840a0_part_2_dragndrop_2.js:52
Loading finished! 

可以看出,文件#2 是最先加载的,因为它是最小的,而#1 是最后加载的,而它是最大的。

于 2013-01-03T09:11:48.950 回答