Control of the issuance of asynchronous results



  • I'm writing a program that shows the image preference by adding it to the tables. There's a field in the neighboring cells for the name, the gate and the source of downloaded photos that I'm also filling, after which I download all this information along with the server files. I use the object. FileReaderwhich, in turn, records files by method readAsDataUrl♪ But the problem is, this method works asynchronously and as a result, I can see the previews not in the order in which the files will be loaded on the server, but the preview itself does not match the files behind them, it's a mix-up. This has created a problem because the descriptions of the file that the user (name, tag, source) does not correspond to the picture.

    That's what it looks like. Loading process:

    загрузка

    Load result:

    результат

    https://stackoverflow.com/questions/19778843/order-issue-with-append-in-a-file-reader People have already raised and solved a similar problem, but I don't know how to use these ideas in my case, when the elements of the table are dynamically created for each bonus. Please help.

    My code is:

    JavaScript

    $(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") {
                //loop for each file selected for uploaded.
    
                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) {
    
                        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": e.target.result,
                            "class": "thumb-image"
                        }).appendTo(newCell4);
    
                    };
    
                    document.getElementById("image-holder").appendChild(newElem);
                    reader.readAsDataURL($(this)[0].files[i]);
                    image_holder.show();
                }
            } else {
                alert("This browser does not support FileReader.");
            }
        } else {
            alert("Please select images only");
        }
    });
    

    });

    HTML:

    <form method="POST" action="upload" enctype="multipart/form-data">
    <input id="fileUpload" name="file" multiple="multiple" type="file"/>
    <br/>
    <input type="submit" value="Upload" class="btn btn-primary btn-lg">
    <br/>
    <div id="image-holder"/>
    </form>



  • For consecutive loading, use may be made https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise

    To this end, FileReader can be loaded into a function that will return the Promise that will be allowed when the picture is downloaded.

    She can look like:

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

    Used https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then You can sign for an event that happens when Prmoise is ready.

    For example:

    loadImage().then(function(imageAsDataUrl){ ... });
    

    Thus, a chain of asynchronous operations can be assembled that will be followed by each other.

    The final view may be:

    var queue = Promise.resolve();
    

    [].reduce.call(this.files,function(queue, file, index){
    return queue.then(function(){
    return loadImage(file).then(function(imageAsDataUrl){
    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);

            $("&lt;img /&gt;", {
                "src": imageAsDataUrl,
                "class": "thumb-image"
            }).appendTo(newCell4);
        });
    });
    

    }, Promise.resolve()).then(function(){
    // все картинки загрузились
    image_holder.show();
    })

    slight derogation: $(this)[0] It's the same as it is. thisYou can check with the following expression $(this)[0] === this Come back. true




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2