0

我试图允许页面初始加载,同时允许同步 ajax 发布调用运行。

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

这是我的两个示例:示例 1 $.post

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在加载每个元素之前不会加载页面。

如何在不等待页面加载的情况下获得两全其美并按顺序加载?我在这里想念什么?

4

2 回答 2

2

JavaScript 只有函数级范围。这意味着该i变量在循环内的迭代之间共享for当每次迭代的回调稍后执行时, (shared)i已达到 21(如您所见)。

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

在确保它们按顺序执行方面;凯文斯的回答是一种将执行推迟到全部完成的干净方式。下面的方式应该在它们到达时按照它们发送的顺序执行它们。

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)));
}  
于 2013-05-23T19:01:36.137 回答
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);
    });
});
于 2013-05-23T19:03:31.543 回答