2016-08-25 4 views
0

Ich baue ein Foto Uploader in Javascript und die bereits hochgeladenen Fotos lesen ich diesen Code habe:Javascript - Async Funktionen falsche Reihenfolge verursacht

// 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 

In der For-Schleife habe ich die bestellten Fotos, aber manchmal wegen der async Funktionen getDataUri() und dataURItoBlob() die Reihenfolge der Elemente in der For-Schleife wird nicht in die Reihenfolge in de UI/DOM übersetzen und die Fotos werden in der falschen Reihenfolge angezeigt. Wie kann ich das verhindern?

Die Asynchron-Funktionen sind dies diejenigen:

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);  
    } 

Irgendwelche Hinweise, wie dieses Problem zu vermeiden?

Mit besten Grüßen,

+0

Erstellen und anhängen 'fileItem' synchron in der Schleife, weil es nicht auf asynchrone Daten angewiesen ist? Oder können Sie nur anhängen, nachdem Sie alle Daten haben? Sammeln Sie alternativ alle Elemente in einem Array, warten Sie, bis alle asynchronen Aufrufe ausgeführt wurden, und hängen Sie dann alle Elemente an. –

Antwort

1

Sie dies durch Speichern der dataurl Werte in einem Array lösen könnte, wie Sie sie erhalten, aber im richtigen Index in diesem Array. Und wenn Sie dann gezählt haben, dass Sie alle diese dataurl Werte erhalten haben, führen Sie die Schleife über diesem Array aus und führen Sie den Elementerstellungscode aus, wie Sie ihn jetzt haben.

// 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); 
      }); 
     }); 
    }); 
}); 
+0

Hallo Trincot. Danke für die Antwort. Der Code scheint alles zu sein, was es nicht funktioniert, ist die "DataURI", wenn ich die "DataURI" innerhalb der "If (! LeftOver) urls.forEach (Funktion (Dataurl) {" Ich bekomme das letzte Bild für alle Wie kann ich das gleiche für diese Variable tun? Mit freundlichen Grüßen, –

+0

Ah ja, das habe ich verpasst. Ich habe gerade den Code aktualisiert, um damit umzugehen. Sehen Sie sich die [Überarbeitungen bearbeiten] an (http://stackoverflow.com/ posts/39151664/revisions) – trincot

+0

Hi wieder Trincot. Ich habe den Code aktualisiert. Aber die Symptome sind genau gleich, ich bekomme das letzte Bild für alle Bilder. Irgendwelche Hinweise ? –

Verwandte Themen