控制 FileReader 结果的顺序

Control the order of FileReader results

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

我发现了一些关于此问题的 ideas,但我不知道如何在我的案例中实现它们,当我将每个预览放在分隔的 table 单元格中并动态创建这些单元格时。

编辑:文件上传到服务器的顺序是正确的。不正确的只是我在上传之前收到的预览顺序。我的意思是,如果我的光盘上有文件 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();
    }

您可以将 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))
}

我找到了解决方案。用异步代码解决此类问题的好作品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");
        }
    });
});