2017-04-27 4 views
0

Ich habe eine ionische (v1) Projekt, das Winkel und Cordova verwendet. Ich bin eine Schleife von einem Array von Dateinamen und Anhängen jeder Datei Daten in einem FormData Objekt, das auf den Server hochgeladen werden muss.Angularjs Versprechen nicht in Controller

Zum Lesen der Dateidaten bietet Cordova/HTML5 einige Methoden, die asynchron sind. Ich verwende Winkels $q Versprechen für den Aufruf dieser Methoden.

Dann möchte ich $q.all verwenden, um zu warten, bis alle Versprechen gelöst sind und den Upload starten.

Aber die Versprechen werden nie gelöst und der aufgelöste Funktionsblock innerhalb $q.all(promises).then wird niemals aufgerufen.

Merkwürdig, wenn ich das Versprechen zurückweise, anstatt es mit deferred.reject zu lösen, ruft es die Fehlermethode von $q.all auf.

Wie löse ich das Versprechen? Hier

ist der Code:

//Inside a controller 
var promises = []; 

for (var key in $scope.rArray) { 
     if ($scope.rArray.hasOwnProperty(key)) { 
      var deferred = $q.defer(); 
      var tmpFile = $scope.rArray[key]; 

      var i = cordova.file.externalRootDirectory + "/" + tmpFile; 

      window.resolveLocalFileSystemURL(i, function(fileEntry) { 
       fileEntry.file(function(file) { 
        var reader = new FileReader(); 
        reader.onloadend = function(e) { 
         console.log('onloadend callled'); 
         var fileBlob = new Blob([this.result], { type:file.type}); 
         fd.append('file', fileBlob,file.name); 
         deferred.resolve(fd); //if reject here it is reflected 
         //$rootScope.$apply(). tried this too 

        }; 
        reader.readAsArrayBuffer(file); 

       }, function(e) { 
        console.log('error getting file', e); 
        deferred.reject(e); 
       }); 
      }, function(e) { 
       console.log('Error resolving fs url', e); 
       deferred.reject(e); 
      }); 

      promises.push(deferred.promise); 
     } 
    }; 

    $q.all(promises).then(function (dataAr) { 
     console.log('promises resolved..'); //NEVER CALLED 
     var request = new XMLHttpRequest(); 
     request.open('POST', ENV.baseUrl+"/st/st"); 
     request.send(fd); 
    }, function errorfn(err) { 
     console.error(JSON.stringify(err)); 
    }) 
+1

aus Ihrer Beschreibung, es wie nicht alle Versprechungen gelöst sind - weshalb q.all niemals fortschreitet - wenn EINE Verheißung ablehnt, q.alle zurückweist, unabhängig vom Zustand der anderen Verheißungen –

+0

'var deferred = $ q.defer();' ist das Problem. .. Der Wert von 'deferred' ist der LETZTE für jeden' ​​deferred.resolve' Aufruf - so kann nur der letzte aufgelöst werden –

Antwort

1

Das Problem ist, dass die var deferred die LETZTE durch die Zeit ist eine der Rückrufe für eine der resolveLocalFileSystemURL Funktionen aufgerufen wird

so, nur ein Versprechen kann jemals gelöst oder abgelehnt werden

mit Promise.all, eine Ablehnung ist genug, um das Versprechen von Promise.all zurückzuweisen - aber alle Versprechen müssen für Versprechen lösen. alle zu lösen

ich ursprünglich mit der Idee eines Verschlusses in Ihrem Code gespielt - aber mit gemeinsamen JS Methoden schien eine viel bessere Lösung - sieht Object.keys und Array # Karte

var promises = Object.keys($scope.rArray).map(function(key) { 
    var tmpFile = $scope.rArray[key]; 
    var deferred = $q.defer(); 
    var i = cordova.file.externalRootDirectory + "/" + tmpFile; 
    window.resolveLocalFileSystemURL(i, function(fileEntry) { 
     fileEntry.file(function(file) { 
      var reader = new FileReader(); 
      reader.onloadend = function(e) { 
       console.log('onloadend callled'); 
       var fileBlob = new Blob([this.result], { type:file.type}); 
       fd.append('file', fileBlob,file.name); 
       deferred.resolve(fd); //if reject here it is reflected 
      }; 
      reader.readAsArrayBuffer(file); 
     }, function(e) { 
      console.log('error getting file', e); 
      deferred.reject(e); 
     }); 
    }, function(e) { 
     console.log('Error resolving fs url', e); 
     deferred.reject(e); 
    }); 

    return deferred.promise; 
}); 
+0

Es funktioniert! Aber ich bin verwirrt. Können Sie den Kontrollfluss in meinem Code erklären? Wie Sie erwähnen, nimmt es immer die letzte Verzögerung für die Auflösung, sollte es nicht die verzögerte nehmen, mit der es ursprünglich aufgerufen wurde. Ich meine, der Spielraum für den asynchronen Rückruf sollte anders sein? – avck