2013-05-08 2 views
5

Ich habe das Filereader API innerhalb einer genannt for-Schleife durchlaufen mehrere Dateiobjekte zu implementieren. Ich benutze FileReader, um die Vorschau von Bildern anzuzeigen.Wie Progress Bar und Rückrufe mit asynchroner Natur des Filereader

function() { 
    for (var i in Files) { 
     var fileReader = new FileReader(); 
     fileReader.readAsBinaryString(Files[i]); 
     fileReader.onload = function() { 

      // do something on FileReader onload 

     } 

     fileReader.onprogress = function(data) { 
      if (data.lengthComputable) {            
       var progress = parseInt(((data.loaded/data.total) * 100), 10); 
       console.log(progress); 
      } 
     } 
    } 

    // do something on completion of FileReader process 
    // actions here run before completion of FileReader 
} 

Ich stoße auf zwei Probleme aufgrund der asynchronen Natur der FileReader API. Zuerst wird das Ereignis onprogress für jede FileReader-Instanz ausgelöst. Dies gibt mir Fortschritte für jede Datei. Während ich beabsichtige, den Gesamtfortschritt für alle Dateien anstelle von einzelnen Dateien anzuzeigen.

Zweitens möchte ich Aktionen auszuführen, die nur dann ausgeführt werden, wenn alle Instanzen (eine für jede Datei) des Filereader abgeschlossen haben. Da FileReader derzeit asynchron funktioniert, werden die Aktionen ausgeführt, bevor FileReader die Aufgabe beendet. Ich habe viel gesucht und dennoch eine Lösung für diese Probleme gefunden. Jede Hilfe wird geschätzt.

Antwort

12

Lassen Sie sich zunächst Ihr zweites Problem lösen. Sie benötigen eine After-Abschluss-Code in einer separaten Funktion zu definieren, und rufen Sie diese Funktion, wenn alle Dateien hochgeladen haben:

function() { 
    var total = Files.length; loaded = 0; 
    for (var i in Files) { 
     var fileReader = new FileReader(); 
     fileReader.readAsBinaryString(Files[i]); 
     fileReader.onload = function() { 

      // do something on FileReader onload 
      loaded++; 

      if (loaded == total){ 
       onAllFilesLoaded(); 
      } 
     } 

     fileReader.onprogress = function(data) { 
      if (data.lengthComputable) {            
       var progress = parseInt(((data.loaded/data.total) * 100), 10); 
       console.log(progress); 
      } 
     } 
    } 
} 

function onAllFilesLoaded(){ 
    //do stuff with files 
} 

Nun, für die Fortschrittserfassung, gibt es ein paar verschiedene Möglichkeiten, wie Sie diese Adresse könnte. Im Moment laden Sie alle Dateien auf einmal, und jede Datei meldet ihren eigenen Fortschritt. Wenn es Ihnen nichts ausmacht, weniger häufige Aktualisierungen des Fortschritts vorzunehmen, können Sie einfach den Onload-Handler verwenden, um den Fortschritt jedes Mal zu melden, wenn eine Datei hochgeladen wird. Wenn Sie wirklich feinkörnig, genaue Fortschritt Updates wollen, werden Sie haben, um die Gesamtgröße aller Dateien kombiniert zu berechnen, dann zu verfolgen, wie viel von jeder Datei geladen hat, und verwenden Sie die Summe dessen, was für jede geladen ist Datei im Vergleich zur Gesamtgröße aller Dateien, um den Fortschritt zu melden.

Wenn Sie dies mit einer Fortschrittsleiste anstelle von console.log implementieren, können Sie für jede Datei, die hochgeladen wird, eine separate Fortschrittsleiste angeben und den Fortschritt für jede Datei genau so berechnen, wie Sie es gerade tun und dann den entsprechenden Fortschrittsbalken aktualisieren. Lassen Sie es mich wissen, wenn das etwas Klärung erfordert.

+2

Nur ein paar Minuten zurück habe ich die gleiche Lösung implementiert und bin zu dieser Frage zurückgekommen, um festzustellen, dass Sie genau das vorgeschlagen haben, was ich implementiert habe. Für den Fortschritt brauche ich keine granularen Werte. So kam ich den Fortschritt wie 'var Fortschritt Berechnung up = parseInt (((geladen/totalNumberOfFiles) * 100), 10);'. Danke für die Hilfe. – John

+0

groß, dies wird hoffentlich auch ein paar andere helfen. – undefined