循环读取图像,等待它们的负载

时间:2013-09-21 19:44:13

标签: javascript loops

没有jQuery

所以,我需要一个能够循环检查页面上所有图像的功能。我需要获得他们的尺寸并验证这些。

function checkImageInputs() {
    var images = new Array();
    var fileInputs = document.getElementsByClassName('file-input');

    for (var i = 0; i < fileInputs.length; i++) {
        var t = fileInputs[i];
        var ourCell = t.parentNode;

        if (t.files[0]) {
            var file = t.files[0];

            fr = new FileReader();
            fr.onload = createImage;
            fr.readAsDataURL(file);

            function createImage() { // Create Image
                img = document.createElement('img');
                img.src = fr.result;
                img.className = 'file-result';
                ourCell.appendChild(img);
                images[i] = img;
            }
        }
    }

    // I need the images array here
    alert(images.length);
}

当我将循环添加到我的函数以处理页面上的所有文件输入时,它不会向我返回想要的结果。

alert返回0,即使我的所有文件输入都填满了图像。

fr.onload之后alert执行其功能。 同样适用于ourCell.appendChild(img),图片显示在alert之后。

如何使alert显示实际的图像数量,等到所有图像都被加载?

我在DOM加载上调用此函数,如下所示:

var fileInputs = document.getElementsByClassName('file-input');
for (var i = 0; i < fileInputs.length; i++) {
    fileInputs[i].onchange = new Function('checkImageInputs()');
}

1 个答案:

答案 0 :(得分:4)

它是异步的,因此在执行createImage回调之前执行长度评估语句。我注意到的另一件事是你使用循环迭代变量将值设置为数组images,在该变量中你有条件。因此,任何与条件不匹配的内容都会在该索引处的数组中创建一个洞,因此数组的长度不会反映数组中的实际项目数。所以使用array.push代替并更好地使用Array文字而不是数组构造函数。这是除非您真的想知道图像是否存在。

所以试试这个:

function checkImageInputs(callback) { //take a callback argument
    var images = [],
       fileInputs = document.getElementsByClassName('file-input'),
       left = 0;
    for (var i = 0; i < fileInputs.length; i++) {
        var t = fileInputs[i];
        var ourCell = t.parentNode;

        if (t.files[0]) {
            var file = t.files[0];
            left++; //increment the count
            var fr = new FileReader(); //If you don't specify a var keyword here fr becomes global
            fr.onload = createImage.bind(this, i); //bind the iteration variable here
            fr.readAsDataURL(file);

            function createImage(itr) { // Create Image
                var img = document.createElement('img'); //If you don't specify a var keyword here img becomes global
                img.src = fr.result;
                img.className = 'file-result';
                ourCell.appendChild(img);
                images.push(img);
                left--; //decrement left count
                if(!left) { //check if this is the last one
                  callback(images); //now make the call back
                }
            }
        }
    }


}

function postProcess(images){
    // I need the images array here
    alert(images.length);
}

checkImageInputs(postProcess); //provide the callback as argument here.

<强> Fiddle

一个解决方案使用ecmaScript5将function.prototype.bind循环迭代变量用于早期浏览器中不可用的函数,但是你也可以使用链接中提到的脚本修补ith。其他选项用封闭物替换它。

变化

fr.onload = createImage.bind(this, i);

fr.onload = (function(i){
            return function(){
                createImage(i);
            }              
        })(i);

<强> Fiddle