所以我有一个针对我公司的长运行查询状态页面,它显示了根据longrunners数量+其他标准改变颜色的不同数据库实例的条形图。
问题是,每次调用更新信息时,颜色都会恢复为默认值,并从头开始构建。这是因为我在检索长队数据时使用$ scope.variable对象来保存颜色信息。
我想将其切换为在函数中使用本地标准变量,并且只有在检索完所有数据后,才将此变量赋值给$ scope.variable。
所以它就像这样:
var getLongrunners = function(){
$scope.longrunnersByInstance = {};
for (var l = 0; l < $scope.swimlanes.length; l++){
$scope.slColor[$scope.swimlanes[l].swimlane] = 0;
}
for (var j = 0; j < instances.length; j++){
$scope.longrunnersByInstance[instances[j].instance] = [];
$scope.instanceColor[instances[j].instance] = 0;
}
for (var i = 0; i < instances.length; i++){
(function(e){
$http
.get('/getLongrunners',{params: {envFlag: '',instance: instances[e].instance}})
.then(function(response){
var longrunners = response.data;
for(var k = 0; k < longrunners.length; k++){
$scope.longrunnersByInstance[instances[e].instance].push(longrunners[k]);
}
if(longrunners.length > $scope.dangerThresh){
$scope.instanceColor[instances[e].instance] = 2;
}else if(longrunners.length >= $scope.warningThresh){
$scope.instanceColor[instances[e].instance] = 1;
}
if($scope.slColor[instances[e].swimlane] < $scope.instanceColor[instances[e].instance]) {
$scope.slColor[instances[e].swimlane] = $scope.instanceColor[instances[e].instance]
}
},getLongrunnersFail);
}(i));
所以我希望$ scope.slColor和$ scope.instanceColor成为常规局部变量,直到此循环结束。
我查看了promises,但是在调用.then()之前,似乎只对$ http有用。
有没有办法制作自定义承诺类型架构并包含多个函数,并且只在完成所有内容后返回承诺?
谢谢!
编辑:
最近尝试:
var promises = [];
var longrunnersByInstance = {};
var instancesPerf = {};
var slColor = {};
var instanceColor = {};
var promiseTest = function() {
$scope.longrunnersByInstance = {};
for (var l = 0; l < $scope.swimlanes.length; l++){
slColor[$scope.swimlanes[l].swimlane] = 0;
}
for (var j = 0; j < instances.length; j++){
instanceColor[instances[j].instance] = 0;
}
instances.forEach(function (instance) {
promises.push($http
.get('/getLongrunners', {
params: {envFlag: 'bh', instance: instance.instance}
})
.then(function (response) {
var longrunners = response.data;
longrunnersByInstance[instance.instance] = [];
for (var k = 0; k < longrunners.length; k++) {
longrunnersByInstance[instance.instance].push(longrunners[k]);
}
if (longrunners.length > $scope.dangerThresh) {
instanceColor[instance.instance] = 2;
} else if (longrunners.length >= $scope.warningThresh) {
instanceColor[instance.instance] = 1;
}
console.log(instance.instance);
if (slColor[instance.swimlane] < instanceColor[instance.instance]) {
slColor[instance.swimlane] = instanceColor[instance.instance]
}
return true;
}, getLongrunnersFail)
);
function getLongrunnersFail(response){
console.log("getting longrunners failed" + response.status);
}
$q.all(promises).then(function () {
// longrunnersByInstance to $scope
console.log('calling all promises callback!');
instances.forEach(function (instance) {
$scope.longrunnersByInstance[instance.instance] = longrunnersByInstance[instance.instance];
});
// instancesPerf to $scope
instances.forEach(function (instance) {
$scope.instancesPerf[instance.instance] = instancesPerf[instance.instance];
});
// slColor to $scope
instances.forEach(function (instance) {
$scope.slColor[instance.instance] = slColor[instance.instance];
});
// instanceColor to $scope
instances.forEach(function (instance) {
$scope.instanceColor[instance.instance] = instanceColor[instance.instance];
});
}, allPromisesFail);
function allPromisesFail(){
console.log("all promises failed")
}
});
};
答案 0 :(得分:3)
Angular使用$q服务处理promises。
它有一个名为all的函数来处理您遇到的问题类型。
这是一个简单的小提琴来演示它:http://jsfiddle.net/ThomasBurleson/QqKuk/
var myApp = angular.module('myApp', []);
function MyCtrl($scope, $q, $timeout) {
var thenFn = function(value){
console.log('resolved ', value);
return value;
},
q1 = $scope.q1 = $q.defer(),
q2 = $scope.q2 = $q.defer(),
p1 = $scope.q1.promise,
p2 = $scope.q2.promise;
$scope.fromThen = $q.all([
p1.then(thenFn),
p2.then(thenFn)
])
.then(function(values) {
console.log(values);
return values;
});
// Must start the AngularJS digest process
// to allow $q.resolve() to work properly
// So use $timeOut() or $apply()
setTimeout(function () {
$scope.$apply( function() {
console.log('resolving delayed promises');
q1.resolve({value : 1});
q2.resolve({value : 2});
});
}, 100, this);
/*
* Alternative approach
*
$timeout( function() {
console.log('resolving delayed promises');
q1.resolve({value : 1});
q2.resolve({value : 2});
});
*/
}
以下是如何将其应用于您的代码(尚未对其进行测试,因此它只是一个方向,但它应该让您前进):
var promises = [];
for (var i = 0; i < instances.length; i++){
//$http return a promise, so you can just push it
promises.push( $http
.get('/getLongrunners',{params: {envFlag: '',instance: instances[e].instance}}));
}
$q.all(promises).then(function(values){
//values should contain an array with all the results you got from all the requests, so you can run through it and aggregate the results
});
答案 1 :(得分:2)
Promise是可链接的:当你在一个promise的成功回调中返回一些内容时,你会得到一个新的promise,它会以返回的值解析。
Example from angular documentation ("Chaining Promises" part):
promiseB = promiseA.then(function(result) { return result + 1; }); // promiseB will be resolved immediately after promiseA is resolved and its value // will be the result of promiseA incremented by 1
因此,在/getLongRunners
回调中,您可以返回一个立即解析的值(如true
),这样您就可以获得一个在回调完成后立即解决的承诺。如果你收集所有这些&#34;孩子&#34;数组中的promise可以将该数组传递给$.all
,并且当所有promise都解析时,即一旦所有回调都完成,它就会解析。
在这里,我用forEach方法替换了for循环并嵌入了立即执行的函数:它更清晰,避免了遇到的闭包问题
var promises = [];
instances.forEach(function(instance, i) {
promises.push($http
.get('/getLongrunners', {
params: {envFlag: '', instance: instances[e].instance}
})
.then(function(response) {
var longrunners = response.data;
// whatever you have to do
return true;
}, getLongrunnersFail);
});
$q.all(promises).then(function() {
// When you are here, all your callbacks will have been executed
});