2013-08-06 164 views
3

有沒有方法跟蹤使用Angular $ http和$ q的http請求進度?我從URL列表中進行$ http調用,然後使用$ q.all返回所有請求的結果。我想跟蹤每個請求的進度(承諾已解決),以便我可以向用戶顯示一些進度。當一個承諾得到解決時,我正在考慮發佈事件,但我不確定應該在哪裏。

 var d = $q.defer(); 
     var promises = []; 
     for(var i = 0; i < urls.length; i++){ 
      var url = urls[i]; 
      var p = $http.get(url, {responseType: "arraybuffer"}); 
      promises.push(p); 
     } 
     $q.all(promises).then(function(result){ 
      d.resolve(result); 
     }, function(rejection){ 
      d.reject(rejection); 
     }); 
     return d.promise; 

編輯: OK,有點擺弄之後,這是我想出

 var d = $q.defer(); 
     var promises = []; 
     var completedCount = 0; 
     for(var i = 0; i < urls.length; i++){ 
      var url = urls[i]; 
      var p = $http.get(url, {responseType: "arraybuffer"}).then(function(respose){ 
       completedCount = completedCount+1; 
       var progress = Math.round((completedCount/urls.length)*100); 
       $rootScope.$broadcast('download.completed', {progress: progress}); 
       return respose; 
      }, function(error){ 
       return error; 
      }); 
      promises.push(p); 
     } 
     $q.all(promises).then(function(result){ 
      d.resolve(result); 
     }, function(rejection){ 
      d.reject(rejection); 
     }); 
     return d.promise; 

不知道這是做的正確的方式。

+1

我認爲這是正確的方式 –

回答

5

我看你已經修改自己的代碼,但如果你需要一個更全面的解決方案,請繼續閱讀

我曾把基於所有待定的HTTP請求(呈現出指標的東西是一個進步的解決方案裝載,有點像youtube有頂部進度條上)

JS:

app.controller("ProgressCtrl", function($http) { 

    this.loading = function() { 
     return !!$http.pendingRequests.length; 
    }; 

}); 

html:

<div id="fixedTopBar" ng-controller="ProgressCtrl as Progress"> 
    <div id="loading" ng-if="Progress.loading()"> 
     loading... 
    </div> 
</div> 

性交

對於我最新的項目它不只是足夠多隻請求調用。我開始使用套接字,webworker,文件系統,filereader,dataChannel和其他使用$q的異步調用。所以我開始研究如何獲得所有未決的承諾(包括$http)。原來沒有任何角度的解決方案,所以我種猴子$q提供者decorating它。

app.config(function($provide) { 

    $provide.decorator("$q", function($delegate) { 
     // $delegate == original $q service 

     var orgDefer = $delegate.defer; 
     $delegate.pendingPromises = 0; 

     // overide defer method 
     $delegate.defer = function() { 
      $delegate.pendingPromises++; // increass 
      var defer = orgDefer(); 

      // decreass no mather of success or faliur 
      defer.promise['finally'](function() { 
       $delegate.pendingPromises--; 
      }); 

      return defer; 
     } 

     return $delegate 
    }); 

}); 

app.controller("ProgressCtrl", function($q) { 

    this.loading = function() { 
     return !!$q.pendingPromises; 
    }; 

}); 

這也許並不適合每個人都需要進行生產,但它可能是對開發人員有用,看是否存在已經被拋在後面,並不會被調用

4

任何未解決的問題做一個小的一般輔助函數:

function allWithProgress(promises, progress) { 
    var total = promises.length; 
    var now = 0; 
    promises.forEach(function(p) { 
     p.then(function() { 
      now++; 
      progress(now/total); 
     }); 
    }) 
    return $q.all(promises); 
} 

然後使用它:

var promises = urls.map(function(url) { 
    return $http.get(url, {responseType: "arraybuffer"}); 
}); 

allWithProgress(promises, function(progress) { 
    progress = Math.round(progress * 100); 
    $rootScope.$broadcast('download.completed', {progress: progress}); 
}).catch(function(error) { 
    console.log(error); 
});