【问题标题】:How to have the foreach loop to wait for $http.get to complete before moving on?如何让 foreach 循环等待 $http.get 在继续之前完成?
【发布时间】:2016-05-04 04:39:28
【问题描述】:

在继续之前,我似乎无法让代码暂停并等待 $http 响应。目前我的代码看起来像这样:

var postAuthorCache = new Array();
angular.forEach($scope.news.posts, function(value, key) {
    console.log(JSON.stringify(postAuthorCache)); //Keeps printing "[]"
    if (!(value["post_author"] in postAuthorCache)) {
        $http.get('/api/tumblr_primaryblog_name/' + value["post_author"]).then(function(response) {
            postAuthorCache[value["post_author"]] = response.data;
            value["post_author_pblog"] = postAuthorCache[value["post_author"]];
            console.log("NOT CACHE: " + value["post_author"]);
        });
    } else {
        value["post_author_pblog"] = postAuthorCache[value["post_author"]];
        console.log("IN CACHE: " + value["post_author"]);
    };
});

但是当它运行时,console.log 输出不是我所期望的。

[]
[]
[]
[]
[]
[]
[]
NOT CACHE: aaaa
NOT CACHE: bbbb
NOT CACHE: aaaa
NOT CACHE: aaaa
NOT CACHE: aaaa
NOT CACHE: aaaa
NOT CACHE: bbbb

我期望的输出是在开始时运行console.log(JSON.stringify(postAuthorCache));,然后在查询$http 之后,它运行console.log("NOT CACHE: " + value["post_author"]); 或console.log("IN CACHE: " + value["post_author"]);。之后,它应该通过再次显示数组对象的字符串化来重复自身,并继续执行NOT CACHE 或IN CACHE 日志语句。

所以问题是,foreach 循环如何等待 $http.get 完成,然后再继续?

【问题讨论】:

  • 有多种方法可以实现这一点,但最好了解您将如何实际使用这些值,因为console.log 消息顺序可能不是您想要的使用方式?如果是,您是否可以手动循环遍历数组,而不是使用forEach,并保持当前index 的运行计数?并且只在.get回调中继续计数index

标签: javascript angularjs foreach


【解决方案1】:

您需要缓存您即将进行查询的事实,例如:

var postRequestCache = {};
var postResponseCache = {};
angular.forEach($scope.news.posts, function(value, key) {
    var author = value["post_author"];
    if (!(author in postRequestCache)) {
        postRequestCache[author] = $http.get('/api/tumblr_primaryblog_name/' + author).then(function(response) {
            postResponseCache[author] = response.data;
        });
    }
});
$q.all(postRequestCache).then(function () {
    angular.forEach($scope.news.posts, function (value, key) {
        var response = postResponseCache[value["post_author"]];
        value["post_author_pblog"] = response.response.blog.title;
    });
});

不过,您可能需要添加一些额外的错误检查。另请注意,可以直接在后一个处理程序中获取响应,而无需通过 postResponseCache,但这更容易。

【讨论】:

    【解决方案2】:

    试试这个代码 -

    var deferred = $q.defer();
        $http.post('/api/tumblr_primaryblog_name/' + value["post_author"]).then(
            function successCallback(response){
                deferred.resolve(response);
                return deferred.promise;
            },
            function errorCallback(response){
                deferred.reject(response);
                return deferred.promise;
            });
    

    【讨论】:

    • 我没有投反对票,但这实际上并没有回答问题的任何部分。这也是多余的,因为$http.post 已经返回了一个承诺。
    【解决方案3】:

    一种方法是使用递归来等待每个调用完成。检查here。

    其他方式是使用承诺链here

    【讨论】:

    • 这应该是评论,而不是答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    相关资源
    最近更新 更多