2013-05-08 9 views
5

Ho chiamato l'API FileReader all'interno di un ciclo for per scorrere più oggetti file. Sto usando FileReader essenzialmente per visualizzare l'anteprima delle immagini.Come implementare la barra di avanzamento e le callback con la natura asincrona del 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 
} 

Sono di fronte a due problemi a causa della natura asincrona dell'API FileReader. Innanzitutto, l'evento onprogress si attiva per ogni istanza di FileReader. Questo mi dà progressi per ogni file. Considerando che, ho intenzione di visualizzare il progresso totale per tutti i file anziché singoli file.

In secondo luogo, voglio eseguire azioni che devono essere eseguite solo quando tutte le istanze (una per ciascun file) di FileReader sono state completate. Attualmente, dal momento che FileReader funziona in modo asincrono, le azioni vengono eseguite prima che FileReader completi l'attività. Ho cercato molto e ancora imbattersi in una soluzione per questi problemi. Qualsiasi aiuto è apprezzato.

risposta

12

Affrontiamo prima il tuo secondo problema. È necessario definire il codice dopo il completamento di una funzione separata, e chiamare tale funzione una volta che tutti i file sono caricati:

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 
} 

Ora, per monitorare i progressi, ci sono un paio di modi diversi si può affrontare questo problema. In questo momento stai caricando tutti i file contemporaneamente e ogni file riporta i propri progressi. Se non ti dispiace aggiornamenti di avanzamento meno frequenti, puoi semplicemente utilizzare il gestore onload per segnalare lo stato di avanzamento ogni volta che un file è stato caricato. Se desideri aggiornamenti di avanzamento accurati e accurati, dovrai calcolare la dimensione totale di tutti i file combinati, quindi tenere traccia della quantità di ciascun file caricato e utilizzare la somma di ciò che è stato caricato per ciascun file. file rispetto alla dimensione totale di tutti i file per segnalare lo stato di avanzamento.

In alternativa, supponendo che si stia implementando questa operazione con una barra di avanzamento anziché con console.log, è possibile fornire una barra di avanzamento separata per ogni file che viene caricato e calcolare il progresso per ogni file esattamente come lo si sta facendo ora , quindi aggiorna la corrispondente barra di avanzamento. Fammi sapere se qualcuno di questi ha bisogno di chiarimenti.

+2

Solo pochi minuti fa ho implementato questa stessa soluzione e sono tornato a questa domanda per scoprire che è successo suggerire esattamente ciò che ho implementato. Per il progresso non ho bisogno di valori granulari. Così ho finito per calcolare il progresso come 'var progress = parseInt (((loaded/totalNumberOfFiles) * 100), 10);'. Grazie per l'aiuto. – John

+0

ottimo, speriamo che questo possa aiutare anche altri. – undefined

Problemi correlati