文件阅读器在javascript中执行多次

时间:2016-04-07 11:29:09

标签: javascript

我正在尝试将图片加载到页面中以供预览,然后使用javascript上传。

我有以下代码:

holder.onclick = function(event) {

    function chooseFile(name) {
        var chooser = $(name);
        chooser.unbind('change');
        chooser.change(function(evt) {

            function loadFile(file, callback) {
                var reader = new FileReader();

                (reader.onload = function(file) {

                    console.log(f);    
                    var output = document.createElement('input');
                    output.type = 'image';
                    output.classList.add('image-responsive');
                    output.classList.add('col-xs-12');
                    output.name = f;
                    output.id = f;
                    output.src = reader.result;

                    var x = document.getElementById('OrigName');
                    x.appendChild(output);

                    return callback(output);
                })(f = file.name);

                reader.readAsDataURL(file);
            }

            for (var i = 0; i < evt.target.files.length; i++) {
                console.log(i);
                var file = evt.target.files[i];
                loadFile(file, function(output) {
                   // console.log(output);
                });
            }
        });
        chooser.trigger('click');
    }
    chooseFile('#fileDialog');
}

问题是,每当我加载图像时,reader.onload方法中的代码执行两次,并且在console i的2x结果中执行console.log(f)和2次错误'找不到localhost / null'。

当我删除(f = file.name)时,脚本执行应该是,但是我在阅读器范围内没有file.name变量。

编辑:

这是我的问题的JSFiddle:

https://jsfiddle.net/onedevteam/udmz34z0/6/

有人可以帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

  

问题是,每当我加载图像时,reader.onload方法内的代码执行两次

这是因为在你的代码中你有这个。

(reader.onload = function(file) {
           //...
           //...
})(f = file.name);  // <---- self executing function.

reader.readAsDataURL(file);

你在reader.onload使用“自我执行功能”,所以当它到达这行代码时会执行一次,而{{1}时再次执行已完成阅读。所以reader.readAsDataURL(file)

  

当我删除(f = file.name)时,脚本执行应该是,但是我在阅读器范围内没有file.name变量。

获取文件名只需将其添加到变量中并像这样使用它。

remove the "self executing function " and you logic will run only once

此外,我觉得不需要将文件名保存到变量中,因为传递给函数的变量var fileName = file.name; reader.onload = function() { //... //... output.name = fileName ; output.id = fileName ; }; // <-- self executing function REMOVED 足以完成工作。以下是根据我的建议的最终代码。

file

答案 1 :(得分:1)

您至少要拨打reader.onload两次。你在另一个函数loadFile()中有这个函数,你可以立即调用它(这就是为什么你只有(f=file.name)时才会看到这种行为的原因),但是在chooser.change函数中你也是有那个调用loadFile()的for循环。也许你可以在file.name以外的地方设置(f=file.name)变量,然后让reader.onload不自动执行。

答案 2 :(得分:1)

您的代码构建方式,您的onload处理程序将执行两次,一次定义时,然后再次“load”事件触发时。将函数定义包装在parens中时:

(reader.onload = function (file) { ... })(f = filename)

你说“定义这个功能并立即执行它。”

你真正想要的是一个返回函数的函数,如下所示:

function makeOnLoadHandler (filename) {
    return function (file) {
        // ... do whatever you need to with file and filename
    };
}

reader.onload = makeOnLoadHandler(someFileName);

外部函数makeOnLoadHandler()filename变量周围创建一个闭包,当内部函数处理读者的load事件时,它会看到filename你在调用makeOnLoadHandler时传入了。