2015-11-02 218 views
0

我有以下服務:競爭條件

app.factory('ParserWebService', function($http, $q, $timeout){ 
    ParserWebService.getParserPfList = function() { 

     var pfData = $q.defer(); 
     var pfList = []; 

     $http.get("https://myurl/parserpf") 
      .then(function(response) { 

       var reponseDataJSON = JSON.parse(response.data); 

       for (var el in reponseDataJSON) { 
        if (reponseDataJSON[el].pf.length > 0) { // Check for non-empty string 
         pfList.push(reponseDataJSON[el]); 
        } 
       } 
console.log("http GET SUCCESS"); 
console.log("pfList.length: " + pfList.length); 

      }) 
      .catch(function(response) { 
       console.error('GET error', response.status, response.data); 
      }) 

console.log(pfList[0]); 

     $timeout(function(){ 
      pfData.resolve(pfList); 
     },1000); 

console.log("pfList.length: " + pfList.length); 
console.log("pfData.promise.length: " + pfData.promise.length); 
     return pfData.promise; 
    } 

    return ParserWebService; 
}); 

當我打電話吧,我第一次得到的錯誤,因爲該服務沒有返回按照剛纔回來之前控制檯打印輸出(見下文)。只有在那之後,我才能在控制檯上看到$ http成功並且pfList.lenght爲109(參見下文)。

pfList.length: 0   <------------------ 
pfData.promise.length: undefined  <---------------- 
mopidId = 0, id = null 
angular.js:11607 TypeError: Cannot read property 'id' of undefined 
    at new <anonymous> (controllers.js:32) 
    at Object.e [as invoke] (angular.js:4185) 
    at $get.w.instance (angular.js:8454) 
    at angular.js:7700 
    at s (angular.js:331) 
    at A (angular.js:7699) 
    at g (angular.js:7078) 
    at g (angular.js:7081) 
    at g (angular.js:7081) 
    at angular.js:6957(anonymous function) @ angular.js:11607$get @ angular.js:8557$get.l.$apply @ angular.js:14502(anonymous function) @ angular.js:1448e @ angular.js:4185d @ angular.js:1446tc @ angular.js:1466Jd @ angular.js:1360(anonymous function) @ angular.js:26176m.Callbacks.j @ jquery.js:3148m.Callbacks.k.fireWith @ jquery.js:3260m.extend.ready @ jquery.js:3472J @ jquery.js:3503 
models.js:599 http GET SUCCESS <--------------- 
models.js:600 pfList.length: 109 <--------------- 

似乎在這裏的競爭條件。爲什麼會發生這種情況,以及如何解決它?謝謝。

+0

典型的JavaScript(沒有任何類型的工人)運行在一個單獨的線程中,我不認爲它與競爭條件有關 – Lucius

回答

2

我認爲你正在使事情變得不必要的複雜。

$http返回一個承諾本身,所以只需從函數返回,並且您將不需要0​​或奇怪的超時。見下面

app.factory('ParserWebService', function($http){ 
    ParserWebService.pfList=[]; 

    ParserWebService.getParserPfList = function() { 

     return $http.get("https://myurl/parserpf") 
      .then(function(response) { 

       var reponseDataJSON = JSON.parse(response.data); 

       for (var el in reponseDataJSON) { 
        if (reponseDataJSON[el].pf.length > 0) { // Check for non-empty string 
         ParserWebService.pfList.push(reponseDataJSON[el]); 
        } 
       } 
      }) 
      .catch(function(response) { 
       console.error('GET error', response.status, response.data); 
      }) 
    } 

    return ParserWebService; 
}); 

的原因,第一個console.log沒有數據,是因爲它不是在then塊,因此執行$http調用有機會完成之前。

如果你使用上面的代碼,以一連串的事件,你會使用它像這樣

ParserWebService.getParserPfList.then(function(){ 
    console.log("All the data is here: ",ParserWebService.pfList); 
}) 

如果您確定上作諾言返回數據的功能,你可以改變你的代碼像這樣:

ParserWebService.getParserPfList = function() { 

    var pfData = $q.defer(); 
    var pfList = []; 

    $http.get("https://myurl/parserpf") 
     .then(function(response) { 

      var reponseDataJSON = JSON.parse(response.data); 

      for (var el in reponseDataJSON) { 
       if (reponseDataJSON[el].pf.length > 0) { // Check for non-empty string 
        pfList.push(reponseDataJSON[el]); 
       } 
      } 
      pfData.resolve(pfList); 

     }) 
     .catch(function(response) { 
      console.error('GET error', response.status, response.data); 
      pfData.reject(); 
     }) 

    return pfData.promise; 
} 

最後一點:如果你指定你期待JSON HTTP調用你不需要事後分析它