jQuery .post / .ajax加载问题

时间:2013-05-23 18:55:52

标签: jquery html

我正在尝试允许页面初始加载,同时允许同步ajax post调用运行。

我尝试过使用$ .post,但这不会按照指定的顺序返回我的输出。它返回先加载的内容。有没有办法同时加载同时仍然允许页面加载?

以下是我的两个例子: 示例1 $。发布

var count = 20;
for(var i = 0; i<=count; i++){
    $.post("page.php", {variables: variables}, function(data){
        $('.container').append(data);
        var card = $('.card').last();
        card.children('.image').append(i);
    });
}

和 示例2 $。ajax

var count = 20;
for(var i = 0; i<=count; i++){
    $.ajax({
        url: "page.php",
        type: "POST",
        data: {
            page: page, 
            count: count,
            idx: i  
        },
        async: false,
    }).done(function(data){
        $('.container').append(data);
        var card = $('.card').last();
        card.children('.image').append(i);
    });
}

他们都“工作”,因为他们从正确的地方拉出我需要的一切,并显示正确的信息。在第一个例子中,它随机加载。无论它首先加载的是什么。即使在我append(i)的帖子中,我也会将数字21附加到所有内容中。就像它经历了循环(异步)并将最后i(21)放在每个元素中。

第二个例子完全按照我想要的方式工作,但当然因为它是async:false,所以在加载每个元素之前它不会加载页面。

如何在不等待页面加载的情况下,充分利用这两个世界并按顺序加载?我在这里缺少什么?

2 个答案:

答案 0 :(得分:2)

JavaScript只有功能级别范围。这意味着i变量在for循环内的迭代之间共享。当每次迭代的回调执行稍后时,(共享)i已达到21(正如您所注意到的那样)。

这是JavaScript的常见问题,只能通过在循环中引入新级别的范围来修复。

确保按顺序执行; Kevins的回答是一种推迟执行的简洁方法,直到所有完成。下面的方式应该按照它们到达时的顺序执行它们。

function doPost(j) {
    $.post("page.php", {variables: variables}, function(data){
        completed[j] = data;

        // Check all the responses have been received for the
        // previous AJAX requests. If we're missing some, bail.
        for (var k=0;k<j;k++) {
            if (!completed[k]) {
                return;
            }
        }

        // If we reach here, our AJAX request has been holding
        // up the show. Execute this, and all successive AJAX
        // requests which have been received.
        for (var k=j;k<completed.length && completed[k];k++) {
            $('.container').append(completed[k]);
            var card = $('.card').last();
            card.children('.image').append(k);                
        }
    });
}

var count = 20;
var completed = new Array(count);
for(var i = 0; i<=count; i++){
    doPost(i);
}

使用Deferreds执行此操作的方法(纯粹是为了有趣和未经测试,但最终更清洁(可以说是)和应该可能有用);

var reqs = [];
var count = 20;

function doPost(i, pendingDeferreds) {
    pendingDeferreds.unshift($.post("page.php", {variables: variables}));

    return jQuery.when.apply(jQuery, pendingDeferreds).done(function (data) {
        data = data[0];

        $('.container').append(data);
        var card = $('.card').last();
        card.children('.image').append(i);
    });
};

for(var i = 0; i<=count; i++){
    reqs.push(doPost(i, reqs.slice(0, i)));
}  

答案 1 :(得分:0)

延期对象。

var count = 20;
var promiseArr = []; // stores promise objects

for(var i = 0; i<=count; i++){
    // push promise objects onto promise array
    promiseArr.push($.ajax({
        url: "scripts/collective/getCards.php",
        type: "POST",
        data: {
            page: page, 
            count: count,
            idx: i  
        }
    }));
}

// when all promise objects in array are resolved, do stuff
$.when.apply($,promiseArr).done(function(){
    // arguments for each request are passed as a single argument, here i iterate over them one by one, in order that they were sent, not received.
    $.each(arguments,function(i,args){
        var data = args[0];
        $('.container').append(data);
        $('.card').children('.image').text(i);
    });
});