Javascript:for循环获取数据但订单被破坏

时间:2015-01-30 03:45:34

标签: javascript ajax angularjs loops

我有一个函数,我使用for循环通过ajax请求获取页面。这一切都很好,除了页面通常是错误的顺序。我想这可能是因为循环内部的异步函数,但我不知道如何解决它。任何建议将不胜感激!

$http.get(link).
        success(function (data) {               
            var num = parseInt($(data).find('.r.m .l').first().text().split(' ').pop());
            var total = num + 1;                

            var pages = [];
            var query = removeLastPart(link);

            for (var i = page; i < total; i++) {
                var full = query + "/" + i + ".html";
                $http.get(full).
                success(function (data) {                       
                    pages.push({image: $(data).find('img#image').attr('src')});
                    j++;
                    if (i == total) {                           
                        cb(pages);
                    }
                }).
                error(function () {
                    console.log("Error getting chapter");
                });
            }

        }).
        error(function () {
            console.log("Error getting page number");
        });

3 个答案:

答案 0 :(得分:3)

由于异步调用您的请求可能无序完成,因此您是正确的。您可以通过使用IIFE或将ajax调用移动到单独的函数并传递应加载页面的索引来解决此问题。

IIFE

for (var i = page; i < total; i++) {
    var full = query + "/" + i + ".html";
    (function(idx){
       $http.get(full).
           success(function (data) {                       
               pages[idx] = {image: $(data).find('img#image').attr('src')};
               j++;
               //assuming j is a counter for knowing when pages are loaded
               if (j == total) {                           
                   cb(pages);
               }
           }).
           error(function () {
              console.log("Error getting chapter");
           });
    })(i);
}

单独的函数调用

function doAjax(url,pageArray,idx,cb){
    $http.get(url).
       success(function (data) {                       
           pageArray[idx] = {image: $(data).find('img#image').attr('src')};
           j++;
           //assuming j is a counter for knowing when pages are loaded
           if (j == total) {                           
               cb(pages);
           }
       }).
       error(function () {
           console.log("Error getting chapter");
       });
}

//....
for (var i = page; i < total; i++) {
    var full = query + "/" + i + ".html";
    doAjax(full,pages,i,cb);
 }

注意,因为$ http调用会返回一个承诺,您可以使用$q.all等待所有页面加载后调用cb(pages)调用而不是递增j并检查(我假设这是你的if cb(pages)的语句是否正在尝试完成)

function doAjax(url,pageArray,idx){
    return $http.get(url).
       success(function (data) {                       
           pageArray[idx] = {image: $(data).find('img#image').attr('src')};
       }).
       error(function () {
           console.log("Error getting chapter");
       });
}

//....
var ajaxCalls = [];
for (var i = page; i < total; i++) {
    var full = query + "/" + i + ".html";
    ajaxCalls.push( doAjax(full,pages,i) );
 }
 $q.all(ajaxCalls).then(function(){
    cb(pages);
 });

答案 1 :(得分:1)

Ajax的定义是异步的,因此您无法确保订单会返回。您可以做的是在输入数据后,您可以自己对数组进行排序。

答案 2 :(得分:1)

也许你可以使用$ q.all,结果将以他们被调用的相同顺序返回,而不管哪一个实际返回。

https://docs.angularjs.org/api/ng/service/$q