我有一个服务,它会执行两个$ http.get来从两个源获取数据并将concat转换为数组并将其返回给控制器。
angular.module('starter.controllers').factory('GetDataList', function ($http) {
var arrDataList = [];
var postData1 = {
"param": "1"
};
var postData2 = {
"param": "2"
};
$http({
method: 'GET',
url: 'https://localhost/search',
data: postData1
})
.then(function (items) {
debugger
arrDataList = arrDataList.concat(items.data.list);
});
$http({
method: 'GET',
url: 'https://localhost/locate',
data: postData2
})
.then(function (items) {
debugger
arrDataList = arrDataList.concat(items.data.list);
});
return {
getAPIData: function () {
debugger
return arrDataList;
}
};
});
在我的控制器中,我称之为:
$scope.GetList = function () {
debugger
$scope.item = GetDataList.getAPIData();
$scope.$broadcast('scroll.infiniteScrollComplete');
}
当我在控制台中使用调试器时,我注意到
1)首先调用getAPIData(),但其中包含数据
2)控制器触发了下一个调试器GetDataList.getAPIData();
没有返回$scope.Item
的任何数据
3)最后一个调试器到达$ http调用,这正如我在控制台中观察到的那样正确地返回数据。但它之后从未到达控制器端,因此移动应用程序中没有显示数据
我读到了角度异步调用的自然行为,所以这似乎是正常的。但就我而言,我该怎么做才能确保数据能够到达控制器?
非常感谢
答案 0 :(得分:0)
您应该按照以下
进行同步var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,serviceDemo) {
$scope.name = 'World';
});
app.factory('serviceDemo', function ($http) {
var arrDataList = [];
var postData1 = []; var postData2 =[]
var firstMethod=function(){
$http({
method: 'GET',
url: 'a.json'
})
.then(function (response) {
console.log(response);
postData1=response.data;
arrDataList.push(postData1);
// console.log(postData1);
secondMethod(); //put the second method call here
});
}
var secondMethod=function(){
$http({
method: 'GET',
url: 'b.json'
})
.then(function (response) {
postData2=response.data;
arrDataList.push(postData2);
console.log(arrDataList);
});
}
var getAPIData= function () {
firstMethod();
return arrDataList;
}
return {
getAPIData: getAPIData
};
});
修改:
您需要在第一个方法的成功块中调用第二个方法。通过这种方式,您的第一个方法被执行,当获取结果时,您的第二个方法被执行,然后只有控制将来自第一个方法块。
<强> LIVE DEMO 强>
答案 1 :(得分:0)
要在不失去性能的情况下实现这一目标,您应该使用$ q.all(),这样它会使您的请求保持异步,并且一旦所有承诺都得到解决,它将返回数据。不要尝试同步方法,因为这会降低您的表现。 您可以像这样使用它:
您的工厂:
app.factory('GetDataList', function($q, $http) {
var promises = [];
var arrDataList = [];
var requests = [{
url: 'https://localhost/search',
postData: {
"param": "1"
}
}, {
url: 'https://localhost/locate',
postData: {
"param": "2"
}
}];
angular.forEach(requests, function(req) {
executeRequest(req);
})
function resolveData(data) {
debugger
if (arrDataList.length === 0) {
arrDataList = data.data;
} else {
arrDataList = arrDataList.concat(data.data);
}
}
function executeRequest(req) {
var promise = $http({
url: req.url,
method: 'GET',
data: req.postData
})
.then(resolveData);
promises.push(promise)
}
return {
getAPIData: function() {
debugger
return $q.all(promises).then(function() {
return arrDataList
});
}
}
});
你的控制器:
$scope.GetList = function() {
debugger
GetDataList.getAPIData().then(function(item) {
$scope.item = item
});
$scope.$broadcast('scroll.infiniteScrollComplete');
}
我们在这里做的是异步执行requests
数组中的每个请求(使用其url
和postData
)并保存数组中的promise。当调用getApiData
时,它返回一个将在$q.all(promises)
之后调用的函数,这意味着它将在所有这些promise完成后返回数据(promises会询问arrDataList
是否为空如果不是,则汇总新数据。
这样你就可以保持异步调用!在控制器内部,您会收到承诺而不是数据本身。