У меня есть следующая услуга:
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 <---------------
Это похоже на состояние гонки. Почему это происходит и как это исправить? Благодарю.
Я думаю, что вы делаете вещи излишне сложными.
$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, вам не нужно будет его анализировать впоследствии