控制FileReader结果的顺序

时间:2016-05-30 19:18:53

标签: javascript jquery html filereader

我的应用可以创建所选图像的预览,将它们放入表格单元格中,让我在上传之前在同一行的其他单元格中填写每个图像(名称,标签,来源)的必要信息。但是有一个问题:我使用FileReader和他的函数readAsDataURL这是异步的。这意味着我以错误的顺序接收预览,并在上传后与其他有关照片的信息不匹配。在这里你可以看到结果 screenshot

我发现了一些关于这个问题的ideas,但是我不知道如何在我的情况下实现它们,当我将每个预览放在separeted表格单元格中并动态创建这些单元格时。

编辑:文件上传到服务器的顺序是正确的。不正确的只是我在上传之前收到的预览顺序。我的意思是,如果我的光盘上有文件1,2,3,我可以按顺序3,1,2接收预览。但是对于服务器,文件将上传为1,2,3。

这是我的功能:

var newElem = document.createElement('table');
newElem.id = 'tl';
newElem.align = 'center';
newElem.border = 0;

    for (var i = 0; i < countFiles; i++) {
        var reader = new FileReader();


        reader.onload = function (e) {

    //create cells for each field

            var newRow = newElem.insertRow(0);
            var newCell1 = newRow.insertCell(0);
            newCell1.innerHTML = "<input type='text' class='form-control' " +
                "placeholder='Source' name='source' style='margin: 15px'>";
            var newCell2 = newRow.insertCell(0);
            newCell2.innerHTML = "<input type='text' class='form-control' " +
                "placeholder='Tags' name='tags' style='margin: 10px'>";
            var newCell3 = newRow.insertCell(0);
                newCell3.innerHTML = "<input type='text' class='form-control' " +
                "placeholder='Name' name='name' style='margin-left: 5px'>";
            var newCell4 = newRow.insertCell(0);
    //append the preview
            $("<img />", {
                "src": e.target.result,
                "class": "thumb-image"
            }).appendTo(newCell4);

        };

        document.getElementById("image-holder").appendChild(newElem);
        reader.readAsDataURL($(this)[0].files[i]);
        image_holder.show();
    }

2 个答案:

答案 0 :(得分:0)

您可以将i传递给IIFE。不确定在this预期$(this)[0].files[i]是什么,尽管该元素也可以作为参数传递给IIFE

for (var i = 0; i < countFiles; i++) {
  (function readFiles(n) { // `i` : `n`
    var reader = new FileReader();
    reader.onload = function(e) {
      //create cells for each field
      var newRow = newElem.insertRow(0);
      var newCell1 = newRow.insertCell(0);
      newCell1.innerHTML = "<input type='text' class='form-control' " +
        "placeholder='Source' name='source' style='margin: 15px'>";
      var newCell2 = newRow.insertCell(0);
      newCell2.innerHTML = "<input type='text' class='form-control' " +
        "placeholder='Tags' name='tags' style='margin: 10px'>";
      var newCell3 = newRow.insertCell(0);
      newCell3.innerHTML = "<input type='text' class='form-control' " +
        "placeholder='Name' name='name' style='margin-left: 5px'>";
      var newCell4 = newRow.insertCell(0);
      //append the preview
      $("<img />", {
        "src": e.target.result,
        "class": "thumb-image"
      }).appendTo(newCell4);

    };

    document.getElementById("image-holder").appendChild(newElem);
    reader.readAsDataURL($(this)[0].files[n]);
    image_holder.show();
  }(i))
}

答案 1 :(得分:0)

我找到了解决方案。为了解决异步代码好问题Promise

的问题

以下是整个工作代码:

$(document).ready(function () {

    $("#fileUpload").on('change', function () {

        //get count of selected files
        var countFiles = $(this)[0].files.length;
        var imgPath = $(this)[0].value;
        var extn = imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase();
        var image_holder = $("#image-holder");
        image_holder.empty();
        if (extn == "gif" || extn == "png" || extn == "jpg" || extn == "jpeg") {
            if (typeof(FileReader) != "undefined") {

                //create the table
                var newElem = document.createElement('table');
                newElem.id = 'tl';
                newElem.align = 'center';
                newElem.border = 0;


                //load all files using Promise
                function loadImage(image) {
                    return new Promise(function (resolve, reject) {
                        var fileReader = new FileReader();
                        fileReader.onload = function (e) {
                            resolve(e.target.result);
                        };
                        fileReader.readAsDataURL(image);
                    });
                }

                //put loaded files into the queue
                var queue = Promise.resolve();

                [].reduceRight.call(this.files, function (queue, file, index) {
                    return queue.then(function () {
                        return loadImage(file).then(function (imageAsDataUrl) {

                            //attach rows with cells to the table
                            var newRow = newElem.insertRow(0);
                            var newCell1 = newRow.insertCell(0);
                            newCell1.innerHTML = "<input type='text' class='form-control' " +
                                "placeholder='Source' name='source' style='margin: 15px'>";
                            var newCell2 = newRow.insertCell(0);
                            newCell2.innerHTML = "<input type='text' class='form-control' " +
                                "placeholder='Tags' name='tags' style='margin: 10px'>";
                            var newCell3 = newRow.insertCell(0);
                            newCell3.innerHTML = "<input type='text' class='form-control' " +
                                "placeholder='Name' name='name' style='margin-left: 5px'>";
                            var newCell4 = newRow.insertCell(0);

                            $("<img />", {
                                "src": imageAsDataUrl,
                                "class": "thumb-image"
                            }).appendTo(newCell4);
                        });
                    });
                }, Promise.resolve()).then(function () {

                    //everything is ready, we can attach the table to imageholder and show it
                    document.getElementById("image-holder").appendChild(newElem);
                    image_holder.show();
                });

            } else {
                alert("This browser does not support FileReader.");
            }
        } else {
            alert("Please select images only");
        }
    });
});