好的,这是上一个问题的重新发布,我对过度简化代码感到困惑......
我有一个angularjs工厂函数,它查询一个解析数据库,并返回一个promise ...到目前为止,非常简单...但是,我的控制器有一个foreach循环,它调用每个id的每一个函数,这意味着然后同时解决。然而,决心不起作用,我所得到的似乎是api调用的混乱。
这是我的代码的简化版本......
app.factory('MyFactory', function($http, $q ) {
return {
testFunction: function (ingredientList) {
var deferred = $q.defer()
ingredientIndex=-1
var regulariseIngredient=function() {
ingredientIndex++
if (ingredientIndex>ingredientList.length-1) {
deferred.resolve(ingredientList);
return
}
(new Parse.Query("Ingredient"))
.equalTo("type", ingredientList[ingredientIndex].type)
.equalTo("name", ingredientList[ingredientIndex].name)
.include("parent")
.find().then(function(result) {
result=result[0]
if(result.get("parent")) result=result.get("parent")
ingredientList[ingredientIndex]=result
regulariseIngredient();
})
}
regulariseIngredient()
return deferred.promise
}
}
}
app.controller('TestController', function($scope,MyFactory) {
recipes = [ An array of objects, each with an ingredients array]
angular.forEach(recipes, function(recipe) {
MyFactory.testFunction(recipe.ingredients).then(function(result) {
console.log(result)
})
})
}
关于服务实际做什么的更多信息......
我的应用程序有一系列食谱和一系列成分。每种成分都有一个'父母',用'合理化'版本代替它。测试函数遍历每个成分,编译结果,然后返回一组替代成分。控制器正在循环配方,这样我就可以检查所有配方的原料。
答案 0 :(得分:2)
@MarkPeace,看来你已经击中反模式"非法" here标题为" The Collection Kerfuffle"。
espoused模式(用于在项目数组的每个成员上并行执行异步任务)是:
function workMyCollection(arr) {
return q.all(arr.map(function(item) {
return doSomethingAsync(item);
}));
}
在您的情况下,doSomethingAsync()
为(new Parse.Query("Ingredient"))...find();
完整的,代码将是:
app.factory('MyFactory', function($http, $q) {
return {
testFunction: function (ingredientList) {
return $q.all(ingredientList.map(function(item) {
return (new Parse.Query("Ingredient"))
.equalTo("type", item.type)
.equalTo("name", item.name)
.include("parent")
.find().then(function(result) {
return result[0].get("parent") || result[0];//phew, that's a bit more concise
});
}));
}
}
});
因此, testFunction()
将返回一系列结果的承诺(无论它们是什么)。
在控制器中,您可以再次使用相同的模式来遍历配方:
app.controller('TestController', function($scope, MyFactory) {
var recipes = [ An array of objects, each with an ingredients array ];
$q.all(recipes.map(function(recipe) {
return MyFactory.testFunction(recipe.ingredients).then(function(results) {
console.dir(results);
return results;
});
})).then(function(arr) {
//all done-and-dusted
//If everything has been successful, arr is an array of arrays of results
//Do awesome stuff with the data.
})['catch'](function(err) {
//report/handle error here
});
});
当然,您在控制器中的确切程度以及工厂(或工厂)的数量取决于您。就个人而言,我会选择让控制器更简单。
答案 1 :(得分:1)
使用$ q.all()将一个promises数组作为参数并返回一个新的promise:
来自doc:
返回将使用值的数组/散列解析的单个promise,每个值对应于promises数组/散列中相同索引/键的promise。如果任何承诺通过拒绝得到解决,则此结果承诺将被拒绝并具有相同的拒绝价值。
对于循环,使用Array.forEach更清晰:
testFunction: function (ingredientList) {
var promiseArray = [];
ingredientList.forEach(function (ingredient) {
var promise = (new Parse.Query("Ingredient"))
.equalTo("type", ingredient.type)
.equalTo("name", ingredient.name)
.include("parent")
.find().then(function(result) {
result = result[0]
if(result.get("parent")) {
result = result.get("parent");
}
return result;
});
promiseArray.push(promise);
});
return $q.all(promiseArray);
}