2015-11-02 1 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 возвращает само обещание, поэтому просто верните это из функции, и вам не понадобится $q или странный таймаут. Ниже

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; 
} 

Конечная нота: если вы указываете на HTTP вызов, который вы ожидаете JSON вам не нужно будет разобрать его после