我有一个数组,我需要逐个通过http post请求将数组的值发送到webservice。对于node.js,我正在使用“async”包为ex:async.eachSeries
做得很好,我怎么能为angular.js做同样的事情,我的正常异步代码;
//this code sends all queries of array (maybe 5.000 request at same time , it is hard to process for webservice :=) ) at same time and wait for all responses.
//it works but actually for me , responses should wait others at end of loop should work one by one
//like async.eachSeries module!
for (var i = 0; i < myArr.lenght; i++) {
(function (i) {
var data = {
"myQuery": myArr[i].query
};
$http.post("/myServiceUrl", data).success(function (result) {
console.log(result);
});
})(i);
}
Matt Way 和 Chris L 回答正确,您可以调查Chris的答案,以了解for循环中异步同步功能。< / p>
答案 0 :(得分:2)
您可以通过将承诺链接在一起来使用$q
来创建类似的要求。例如:
var chain = $q.when();
angular.forEach(myArr, function(item){
chain = chain.then(function(){
var data = {
myQuery: item.query
};
return $http.post('/myServiceUrl', data).success(function(result){
console.log(result);
});
});
});
// the final chain object will resolve once all the posts have completed.
chain.then(function(){
console.log('all done!');
});
基本上,只要前一个承诺完成,您就会运行下一个承诺。这里强调的是,根据您的问题,每个请求都将等到上一个请求完成。
答案 1 :(得分:1)
如果我理解你的问题。您希望以同步方式运行for循环,以便下一次迭代仅在上一次迭代完成后发生。为此,您可以使用同步循环/回调。特别是如果订单很重要。
var syncLoop = function (iterations, process, exit) {
var index = 0,
done = false,
shouldExit = false;
var loop = {
next: function () {
if (done) {
if (shouldExit && exit) {
return exit(); // Exit if we're done
}
}
// If we're not finished
if (index < iterations) {
index++; // Increment our index
process(loop); // Run our process, pass in the loop
// Otherwise we're done
} else {
done = true; // Make sure we say we're done
if (exit) exit(); // Call the callback on exit
}
},
iteration: function () {
return index - 1; // Return the loop number we're on
},
break: function (end) {
done = true; // End the loop
shouldExit = end; // Passing end as true means we still call the exit callback
}
};
console.log('running first time');
loop.next();
return loop;
}
对于您的特定实施:
syncLoop(myArray.length, function (loop) {
var index = loop.iteration();
var data = {
"myQuery": myArray[index].query
};
$http.post("/myServiceUrl", data).success(function (result) {
console.log(result);
loop.next();
});
}, function () {
console.log('done');
});
如果您打算在返回数据后执行某些操作(例如执行计算),则可以使用此方法执行此操作,因为您将按指定的顺序返回数据。
我在我构建的统计计算网络应用程序中实现了类似的东西。
修改强>
为了说明我在使用$ q时遇到的问题。当我设置了一个小提琴时。希望这有助于说明我为什么这样做。
https://jsfiddle.net/chrislewispac/6atp3w8o/
使用Matt的答案中的以下代码:
var chain = $q.when(promise.getResult());
angular.forEach(myArr, function (item) {
chain = chain.then(function () {
$rootScope.status = item;
console.log(item);
});
});
// the final chain object will resolve once all the posts have completed.
chain.then(function () {
console.log('all done!');
});
这个小提琴就是我解决方案的一个例子:
https://jsfiddle.net/chrislewispac/Lgwteone/3/
将$ q版本与我的版本进行比较。查看控制台并想象那些被传递到用户界面的用户界面,以便用户干预流程和/或对顺序退货执行统计操作。
您将看到它不会在控制台或Matt的答案视图中依次给出数字1,2,3,4等。它批量&#39;响应然后返回它们。因此,如果不根据步骤2中的响应运行步骤3,则至少在所提供的答案中,没有在这里中断或明确控制同步操作的方法。当尝试执行顺序计算和/或允许用户控制断点等时,这会出现严重问题。
现在,我正在挖掘$ q库和Q库,看看是否有更优雅的解决方案来解决这个问题。但是,我的解决方案确实按照要求工作,并且非常明确,这允许我将函数放在服务中并根据我的意愿操作某些用例,因为我完全理解它在做什么。对我来说,这比使用库更重要(至少在我作为程序员开发的这个阶段,我确信在StackOverflow的同一阶段还有很多其他人)。
答案 2 :(得分:1)
function logResultFromWebService(value)
{
$http.post("/myServiceUrl", value).success(console.log);
}
angular.forEach(myArray, logResultFromWebService);
答案 3 :(得分:0)
如果订单与发送无关紧要
var items = [/* your array */];
var promises = [];
angular.forEach(items, function(value, key){
var promise = $http.post("/myServiceUrl", { "myQuery": value.query });
promises.push(promise);
});
return $q.all(promises);