我有一个工具,它将大型查询拆分为可管理的块,然后使用简单的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%正确,只是偶尔出现问题并不总是按顺序附加。
完成所有循环并将其附加到容器后,我想运行一些代码来确认操作已完成。
非常感谢,希望这很清楚
答案 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种选择。
进行ajax的异步调用。您将在此答案jQuery ajax success anonymous function scope中获得有关它的详细信息。但是再次..建议回调,不要做异步错误。相反,.when()
或.then()
更容易..因为最终它们也是回调。
递归函数可以帮助您完成此类任务。这是一种肮脏的方法,因为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');
}