2017-04-27 17 views
0

角度とコードを使用するionic(v1)プロジェクトがあります。 ファイル名の配列をループし、各ファイルデータをFormDataオブジェクトに追加します。このオブジェクトはサーバーにアップロードする必要があります。Angularjsはコントローラで解決されないと約束します

ファイルデータを読み込むために、Cordova/HTML5には非同期のメソッドがいくつかあります。私はこれらのメソッドを呼び出すための角度の$qを使用しています。

次に、すべての約束が解決するまで待ってからアップロードを開始するには、$q.allを使用します。

しかし、約束は決して解決されず、$q.all(promises).thenの解決された機能ブロックは決して呼び出されません。

私が約束を拒否する代わりに、deferred.rejectと解決するのではなく、エラーメソッド$q.allを呼び出します。

私は約束をどのように解決しますか?ここで

は、コードは次のとおりです。

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

あなたの説明から、それが見えますすべての約束が解決されたわけではない - それで、q.allは決して進歩しない - なぜなら、約束が拒否されたとき、q.allは他の約束の状態にかかわらず拒否する。 –

+0

'var deferred = $ q.defer();'が問題である。 .. 'deferred'の値はすべての' deferred.resolve'呼び出しのLAST ONEになります - 最後のものだけを解決することができます –

答えて

1

問題がvar deferredのみ、resolveLocalFileSystemURLのいずれかの機能のためのコールバックのいずれかのように

と呼ばれる時間によってLAST ONEであるということです1つの約束を解決または拒否することができます

Promise.allでは、Promise.allによって返されたPromiseを拒否するには1つの拒否で十分ですが、すべての約束はPromiseで解決する必要があります。

を解決するために、すべての私はもともとあなたのコード内の閉鎖のアイデアをおもちゃに - しかし、一般的なJSの方法は、はるかに優れたソリューションを思え使用して - Object.keysと配列番号マップ

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

これは機能します!しかし、私は混乱しています。私のコードでコントロールの流れを説明できますか?あなたが言及しているように、最後に解決のために最後に延期されたものを取っています。最初に呼び出された延期を取るべきではありません。私は、非同期コールバックのスコープが異なるはずですか? – avck

関連する問題