异步请求进入for for angular angular.js

时间:2015-10-17 00:45:58

标签: javascript angularjs node.js asynchronous

我有一个数组,我需要逐个通过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>

4 个答案:

答案 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);