1

我在離子項目中使用ngCordova文件傳輸插件從urls下載圖像集。這是我爲此使用的代碼。這裏在每個角度內同步調用函數

// Save a image file in a given directory 
$scope.saveImage = function(dir,imgUrl,imageName) { 

    var url = imgUrl; 
    var targetPath = cordova.file.dataDirectory+ dir+"/" + imageName; 
    var trustHosts = true; 
    var options = {}; 

    // Download the image using cordovafiletransfer plugin 
    $cordovaFileTransfer.download(url, targetPath, options, trustHosts) 
    .then(function(result) { 
     $scope.loadedCount ++; 
     $ionicLoading.show({template : "<ion-spinner class='spinner-energized'></ion-spinner><p> Downloading pages : "+ $scope.loadedCount+" of "+ $scope.pages.length+ "</p><p>Please wait...</p><p><button class=\"button button-block button-positive\">continue in background</button></p>"}); 
     if($scope.loadedCount == $scope.pages.length) { 
      $ionicLoading.hide(); 
      $scope.showDownloadSuccessAlert = function() { 
       var alertPopup = $ionicPopup.alert({ 
        title: 'Success!', 
        template: "Your magazine successfully downloaded. You can view it on Downloads!" 
       }); 
      }; 
      $scope.showDownloadSuccessAlert(); 
     } 
    }, function(err) { 
     alert(JSON.stringify(err)); 
    }, function (progress) { 
     if($scope.loadedCount > 80) { 
     } 
    }); 
}; 

// Download the current magazine 
$scope.downloadMagazine = function() { 
    if($rootScope.user.user_id == undefined) { 
     $scope.showLoginAlert = function() { 
       var alertPopup = $ionicPopup.alert({ 
        title: 'Oops!', 
        template: "Your must login to download magazines" 
       }); 
      }; 
     $scope.showLoginAlert(); 
     return; 
    } 

    document.addEventListener('deviceready', function() { 

     var dirName = $rootScope.currentIssue.slug+'_VOL_'+$rootScope.currentIssue.vol+'_ISU_'+$rootScope.currentIssue.issue; 

     // First create the directory 
     $cordovaFile.createDir(cordova.file.dataDirectory, dirName, false) 
     .then(function (success) { 
      var count = 1; 
      $scope.loadedCount = 0; 
      angular.forEach($scope.pages, function(value, key) { 
       var imgName = count+".png"; 
       $scope.saveImage(dirName,value.link,imgName); // Then save images one by one to the created directory. 
       count++; 
      }); 

     }, function (error) { 
      // Directory already exists means that the magazine is already downloaded. 
      $scope.showDownloadedAlert = function() { 
       var alertPopup = $ionicPopup.alert({ 
        title: 'Why worry!', 
        template: "Your have already downloaded this magazine. You can view it on downloads" 
       }); 
      }; 
      $scope.showDownloadedAlert(); 
     }); 

    }, false); 
}; 

})

問題是,程序試圖無需等待前一個完成一次下載的一切。如何等待一個文件完成下載,然後啓動另一個文件?

感謝

回答

1

如果你想自動做到這一點(你是不是第一個:How can I execute array of promises in sequential order?),你可以嘗試減少地址列表,以一個單一的承諾,將做全產業鏈。

$scope.pages.reduce(function (curr,next) { 
     return curr.then(function(){    
      return $scope.saveImage(dirName, curr.link, imgName); 
     }); 
    }, Promise.resolve()).then(function(result) { 

     $ionicLoading.show({template : "<ion-spinner class='spinner-energized'></ion-spinner><p> Downloading pages : "+ $scope.loadedCount+" of "+ $scope.pages.length+ "</p><p>Please wait...</p><p><button class=\"button button-block button-positive\">continue in background</button></p>"}); 
     if($scope.loadedCount == $scope.pages.length) { 
      $ionicLoading.hide(); 
      $scope.showDownloadSuccessAlert = function() { 
       var alertPopup = $ionicPopup.alert({ 
       title: 'Success!', 
       template: "Your magazine successfully downloaded. You can view it on Downloads!" 
      }); 
     }; 
     $scope.showDownloadSuccessAlert(); 
    } 
    }); 

而且不要忘記,讓您的saveImage異步返回一個promise

UPDATE:

您將需要從您刪除,然後邏輯保存方法,並返回download方法調用:

return $cordovaFileTransfer.download(url, targetPath, options, trustHosts).promise; 

然後你就可以把你下載處理器連接到Promise.resolve()).then。往上看。

+0

能否請您解釋一下「讓你的'saveImage'異步返回一個'promise'對不起,我是新手 –

+0

你可以發表saveImage的代碼? – Yaser

+0

代碼已更新。請查看 –

0

除了鏈接你的承諾之外沒有別的辦法。這裏有一個例子:

angular.module('app', []) 
 
    .service('fakeDownloadService', function($timeout) { 
 
    this.download = (file) => $timeout(() => file, 100); 
 
    return this; 
 
    }) 
 
    .run(function($rootScope, $q, fakeDownloadService) { 
 
    var listOfFiles = []; 
 
    for (var i = 0; i < 10; i++) 
 
     listOfFiles.push('file' + i); 
 
    $rootScope.log = []; 
 
    $rootScope.download =() => { 
 
     listOfFiles 
 
     .reduce((prev, curr) => { 
 
      return prev.then((result) => { 
 
      if(result) 
 
      $rootScope.log.push(result + ' downloaded'); 
 
      return fakeDownloadService.download(curr); 
 
      }); 
 
     }, $q.resolve()) 
 
     .then(() => $rootScope.log.push('all done')); 
 
    }; 
 
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script> 
 
<div ng-app="app"> 
 
    <button ng-click="download()">Start</button> 
 
    <div>Log:</div> 
 
    <ul> 
 
    <li ng-repeat="entry in log track by $index"> 
 
     {{entry}} 
 
    </li> 
 
    </ul> 
 
</div>