Javascript -异步函数导致不正确的顺序

Javascript - Async functions causing incorrect order

本文关键字:不正确 顺序 异步 函数 Javascript      更新时间:2023-09-26

我正在用Javascript构建一个照片上传器,为了读取已经上传的照片,我有以下代码:

    // Populate with existing photos
    var index;
    for (index = 0; index < params.photosToPopulate.length; ++index) {
        // Get the data of the image
        getDataUri(params.photosToPopulate[index], params, function(dataURI){
            // Get the Blob
            dataURItoBlob(dataURI, function(dataurl){
                var blob = URL.createObjectURL(dataurl);
                // fileItem
                var fileItem = document.createElement("div");
                fileItem.setAttribute('angle', 0);
                fileItem.setAttribute('blob', blob);
                fileItem.className = 'imageloaderplusFile';
                filesdiv.appendChild(fileItem);
                // fileImg
                var fileImg = document.createElement("div");
                fileImg.className = 'imageloaderplusImage';
                fileImg.style.backgroundImage = 'url(' + dataURI + ')';
                fileItem.appendChild(fileImg);
                // fileRotate
                var fileRotate = document.createElement("div");
                fileRotate.className = 'imageloaderRotate';
                fileRotate.setAttribute('title', 'Rotate');
                fileItem.appendChild(fileRotate);
                fileRotate.onclick = function(){
                    var angle;
                    switch(parseInt(this.parentNode.getAttribute('angle'))){
                        case 0:
                            angle = 90;
                            break;  
                        case 90:
                            angle = 180;
                            break;
                        case 180:
                            angle = 270;
                            break;
                        case 270:
                            angle = 0;
                            break;
                    }
                    this.parentNode.setAttribute('angle', angle);
                    // css
                    var image = this.parentNode.firstChild;
                    image.style.webkitTransform = 'rotate(' + angle + 'deg)'; 
                    image.style.mozTransform = 'rotate(' + angle + 'deg)'; 
                    image.style.msTransform = 'rotate(' + angle + 'deg)';
                    image.style.oTransform = 'rotate(' + angle + 'deg)';
                    image.style.transform = 'rotate(' + angle + 'deg)';
                    // draw
                    ImageLoaderPlus.draw(this.parentNode, params);
                }
                // fileRemove
                var fileRemove = document.createElement("div");
                fileRemove.className = 'imageloaderRemove';
                fileRemove.setAttribute('title', 'Remove');
                fileItem.appendChild(fileRemove);
                fileRemove.onclick = function(){
                    this.parentNode.parentNode.removeChild(this.parentNode);
                }
                // draw
                ImageLoaderPlus.draw(fileItem, params); 
            });
        });
    } // End For Loop

在For循环中,我有有序的照片,但有时由于异步函数getDataUri()和dataURItoBlob(), For循环中项目的顺序将无法转换为de UI/DOM中的顺序,并且照片以不正确的顺序显示。我怎样才能避免这种情况的发生?

异步函数是这样的:

    function getDataUri(url, params, callback) {
        var image = new Image();
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        //image.crossOrigin = "anonymous";  // This enables CORS
        // get scale
        var scale = (params.resize && (image.width > params.maxWidth || image.height > params.maxHeight)) ? Math.min(params.maxWidth / image.width, params.maxHeight / image.height) : 1;
        image.onload = function (event) {
            try {
                canvas.width = Math.round(image.width * scale);
                canvas.height = Math.round(image.height * scale);
                ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
                //console.log( ctx.canvas.toDataURL('image/jpeg', params.jpegQuality) );
                result = ctx.canvas.toDataURL('image/jpeg', params.jpegQuality)
                callback(result);
            } catch (e) {
                alert(e);
            }
        };
        image.src = url;
    }       
    // To convert URL to Blob
    function dataURItoBlob(dataURI, callback) {
            // convert base64 to raw binary data held in a string
            // doesn't handle URLEncoded DataURIs
            var byteString;
            if (dataURI.split(',')[0].indexOf('base64') >= 0) {
                byteString = atob(dataURI.split(',')[1]);
            } else {
                byteString = unescape(dataURI.split(',')[1]);
            }
            // separate out the mime component
            var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
            // write the bytes of the string to an ArrayBuffer
            var ab = new ArrayBuffer(byteString.length);
            var ia = new Uint8Array(ab);
            for (var i = 0; i < byteString.length; i++) {
                ia[i] = byteString.charCodeAt(i);
            }

            try {
                result = new Blob([ab], {type: mimeString});
                //return new Blob([ab], {type: mimeString});
            } catch (e) {
                // The BlobBuilder API has been deprecated in favour of Blob, but older
                // browsers don't know about the Blob constructor
                // IE10 also supports BlobBuilder, but since the `Blob` constructor
                //  also works, there's no need to add `MSBlobBuilder`.
                var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder;
                var bb = new BlobBuilder();
                bb.append(ab);
                result = bb.getBlob(mimeString);
                //return bb.getBlob(mimeString);
            }
            callback(result);       
    }

关于如何避免这个问题有什么线索吗?

问好,

您可以通过在收到dataurl值时将它们存储在数组中来解决这个问题,但是存储在该数组的正确索引处。然后,当您计算收到的所有dataurl值时,您将在该数组上执行循环并执行元素创建代码,就像现在一样。

// Intermediate array to store the dataURI and dataurl values in order
var urls = [];
var URIs = [];
// Keep count of how many dataurl values we received
var leftOver = params.photosToPopulate.length;
// Iterate in a way that you create a new closure on every iteration, 
// each iteration has its proper index variable
params.photosToPopulate.forEach(function (photo, index) {
    // Get the data of the image
    getDataUri(photo, params, function(dataURI){
        // Store at the right place in our array
        URIs[index] = dataURI;
        // Get the Blob
        dataURItoBlob(dataURI, function(dataurl){
            // Only store the url at the right place in our array
            urls[index] = dataurl;
            // ... and update the count
            leftOver--;
            // All done? Then iterate over the dataurl values in the correct order
            if (!leftOver) urls.forEach(function(dataurl, index) {
                var dataURI = URIs[index]; // get correct dataURI
                var blob = URL.createObjectURL(dataurl);
                // fileItem
                var fileItem = document.createElement("div");
                // ...etc, all your element creation code comes here, unchanged. 
                // ...
                // draw
                ImageLoaderPlus.draw(fileItem, params); 
            });
        });
    });
});