【问题标题】:Async request into for loop angular.js异步请求进入for循环angular.js
【发布时间】:2015-10-17 00:45:57
【问题描述】:

我有一个数组,我需要通过http post请求将数组的值一一发送到webservice。对于 node.js ,我正在使用“async”包来做到这一点,例如: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 WayChris L 都回答 Correct ,您可以研究 Chris 的回答以了解 for 循环中的异步同步功能。

【问题讨论】:

  • 顺序重要吗?
  • 你可以在浏览器中使用async包和angular的$http。您唯一遇到的问题是,如果您想用结果更新您的$scope,那么您可能需要使用$scope.$apply$timeout(没有可选延迟)

标签: javascript angularjs node.js asynchronous


【解决方案1】:

您可以使用 $q 通过将 Promise 链接在一起来创建类似的需求。例如:

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!');
});

基本上你只是在前一个承诺完成后运行下一个承诺。根据您的问题,在此强调每个请求都将等到前一个请求完成。

【讨论】:

  • $q 是 Angular 的 Promise 库,从一开始就是 Angular 的。到目前为止,Promise 是使用 $http 的正确方法,而不是您标记为正确的复杂答案。如果您创建小提琴,我们可以为您提供帮助。
  • @MattWay q 库的问题出现在您执行大型顺序计算并以顺序方式处理数据时需要错误处理以提醒用户提供更多输入等。这取决于您的用例根据我在统计计算应用程序中的实施尝试,您的一揽子陈述并不完全正确
  • 您的评论毫无意义?这个问题与“大型顺序计算”有什么关系? Osman 想要执行一系列 $http 调用,而这个答案使用 Promise 来实现,这是 $q 的意图。不过,我很好奇您对 $q 问题的看法,这可能是一个很好的问题。
  • ps。 @MattWay 。我自己还是比较新的。我正在讨论这个问题,以向更有经验的开发人员学习。请不要将我的谈话解释为“争论”,因为它正在窥探更有经验的人。很难用文字说清楚。此致,克里斯
  • 好的,兄弟,我进行了调查,现在我正在考虑为 Angular 创建一个异步模块:P,这很有说明性,我希望我可以选择两个答案都是正确的 :)
【解决方案2】:
function logResultFromWebService(value)
{
    $http.post("/myServiceUrl", value).success(console.log);
}

angular.forEach(myArray, logResultFromWebService);

【讨论】:

    【解决方案3】:

    如果我正确理解您的问题。您希望以同步方式运行 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 等。它“批处理”响应,然后返回它们。因此,如果根据步骤 2 中的响应不运行步骤 3,则至少在提供的答案中,没有一种方法可以中断或显式控制此处的同步操作。当尝试执行顺序计算和/或允许用户控制断点等时,这会带来一个重大问题。

    现在,我正在研究 $q 库和 Q 库,看看是否有更优雅的解决方案来解决这个问题。但是,我的解决方案确实按要求工作并且非常明确,这使我可以将功能放置在服务中并根据我的意愿对某些用例进行操作,因为我完全理解它在做什么。对我来说,这比使用库更重要(至少在我作为程序员的开发的这个阶段,我相信在 StackOverflow 上还有很多其他人处于同一阶段)。

    【讨论】:

    • 我想我误解了你的问题?
    • 没关系,每个请求的响应都用这个代码互相等待,谢谢你的大力帮助:),此外,这个答案对其他人非常有用。
    • 虽然这个答案在技术上有效,但它不是一个好的解决方案。
    • 很抱歉,您对我的回答 @MattWay 似乎很不高兴。也许,如果您提供一个小提琴,按照定义的顺序执行数据驱动计算并进行错误处理并将其展示给我们,您可以启发我们双方,而不是仅仅说“它有效但它不好”。这对每个人来说都是一次学习经历,建设性的批评是参与这里的全部重点。 :-)
    • 我确实提供了更正确的答案。您所写的基本上是 $q 为您所做的简化自定义版本。您是否同意重新发明轮子可能不是最好的方法?
    【解决方案4】:

    如果发送顺序无关紧要

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

    【讨论】:

    • 我相信这仍然会同时发送所有请求,而不是关于顺序。
    猜你喜欢
    • 1970-01-01
    • 2017-11-22
    • 2019-07-21
    • 2016-04-09
    • 2016-09-27
    • 2018-11-11
    • 2017-05-19
    • 1970-01-01
    相关资源
    最近更新 更多