在'for'循环完全完成之前,没有延迟功能

时间:2016-09-20 10:53:12

标签: javascript php jquery ajax loops

我有一个工具,它将大型查询拆分为可管理的块,然后使用简单的AJAX方法将其吐出。 AJAX表单的目标只是一个脚本,它将一些表单数据委托给一个函数,包括要处理的“块”。

<script>                

var passes = Math.ceil($max / $offset);

for (i = 0; i < passes; i++)
{

    $.ajax({
        type: 'POST', url: 'do.php?p=' + i, data: $('#form" . $i . "').serialize(),
    success: function(data){ 
        $('#update" . $i . "').append(data);  
    }
    });
}
</script>

因为这可以迭代几次,所以我想在循环(即函数本身)完成时执行一个脚本。

由于这不是太时髦,我认为将if(i == passes -1) { alert('test');}if(i == passes -1) { alert('test');}添加到循环的结尾会是一个简单的例子,如下所示:

for (i = 0; i < passes; i++) {

    $.ajax({
        type: 'POST', url: 'do.php?p=' + i, data: $('#form" . $i . "').serialize(),
    success: function(data){ 
        $('#update" . $i . "').append(data);  
    }
    });

    if(i == passes -1) { alert('test');}

}

....但是一旦页面加载,就会在循环之前加载它。

同样,在循环之后添加一个简单的函数也可以获得相同的结果。

我原本以为(但我对JS很新鲜)它会在尝试执行'i'的第二个实例之前完成一个循环,但它似乎没有这样做 - 页面就像所有请求立即发送,完成循环,执行代码,然后允许“成功”内的功能在他们自己的时间回显。这似乎更加明显,因为它有时会在第一次迭代i之前附加结果。

问题...

1)考虑到目的,我是否在构建循环时出错?

2)为什么循环似乎在循环之后执行代码时似乎它仍在处理循环本身?

我想要实现的目标

每个循环都应该执行MySQL查询,返回函数的HTML输出,然后打印它,然后继续下一个。它确实这样做了99%正确,只是偶尔出现问题并不总是按顺序附加。

完成所有循环并将其附加到容器后,我想运行一些代码来确认操作已完成。

非常感谢,希望这很清楚

3 个答案:

答案 0 :(得分:1)

这是一个承诺&#34;基于你的问题的解决方案。

首先,将每个传递分解为执行一个工作单元的函数:

function makePass(i) {
    return $.ajax({
        type: 'POST', url: 'do.php?p=' + i, data: $('#form' + i).serialize()
    }).then(function(data) {
        $('#update' + i).append(data); 
    });
}

然后你可以创建一个通用函数,伪递归地对所提供的函数进行所需的调用次数,每次使用当前的传递号调用它,最后返回一个新的&#34;已解决的&#34;每一次传递都完成后承诺:

function makeNPasses(f, n) {
    var i = 0;
    return (function loop() {
        if (i < n) {
            return f(i++).then(loop);
        } else {
            return Promise.resolve();
        }
    })();
}

然后,您可以在完成所有操作后注册要调用的处理程序:

var passes = Math.ceil($max / $offset);

makeNPasses(makePass, passes).then(function() {
    console.log("All done!");
});

答案 1 :(得分:0)

Javascript有一个异步流..它不会等待上述请求从某个地方获取数据......相反,它只是继续触发语句。

要逃避这一点,有3种选择。

  1. 理想的方法是向服务器发出1个单一的http请求,并以json数组的形式获取所有数据。这将更有效,更容易,更省时,并且遵循最佳实践。
  2. 进行ajax的异步调用。您将在此答案jQuery ajax success anonymous function scope中获得有关它的详细信息。但是再次..建议回调,不要做异步错误。相反,.when().then()更容易..因为最终它们也是回调。

  3. 递归函数可以帮助您完成此类任务。这是一种肮脏的方法,因为ES5不会让你使用递归函数进行更深入的迭代。但是ES6确实允许10000次迭代。但它不是一个好方法。它会增加开销并阻碍页面加载。

答案 2 :(得分:-1)

AJAX调用是异步的,因此它们在循环结束之前无法成功(因为JavaScript是非阻塞的)。实际上你想要做的是在AJAX调用之后执行操作,而不仅仅是在循环之后(这是同步的)所以我建议使用Promise或链接或聚合成功事件,如下所示:

var passes = Math.ceil($max / $offset);
for (i = 0; i < passes; i++) {
    $.ajax({
        type: 'POST',
        url: 'do.php?p=' + i,
        data: $('#form' + i).serialize(),
        success: function(data){ 
            $('#update' + i).append(data);
            resolve();
        },
        error: reject
    });
}

var resolved = 0;
function resolve() {
    if(++resolved >= passes) {
        alert('test');
    }
}

function reject() {
    alert('One of AJAX requests failed');
}