未能延时功能,直到后for循环已全面完成
我有到位被拆分大型查询到管理的小块,然后用一个简单的AJAX方法吐出了这一点的工具。 AJAX表单的目的地只是一个将某些表单数据委托给函数的脚本,包括处理哪个“块”。未能延时功能,直到后for循环已全面完成
<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%正确,只是偶尔出现的问题并不总是按顺序排列。
毕竟循环已经完成,并追加到容器中,我想运行一些代码来确认操作完成。
许多在此先感谢,希望这是不够清楚
这是针对您的问题的“承诺”解决方案。
首先,分解每一个进入,做一个工作单元的功能:
function makePass(i) {
return $.ajax({
type: 'POST', url: 'do.php?p=' + i, data: $('#form' + i).serialize()
}).then(function(data) {
$('#update' + i).append(data);
});
}
然后你就可以做出一个通用的函数,伪递归将调用所提供的功能所需的号码,主叫每次用当前通号它,最后返回一个新的“解决”的承诺一次通已经完成:
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!");
});
Brilliant。完全符合计划。我必须研究它才能真正理解这是如何完成的,但它看起来像是一个绝妙的解决方案。谢谢! –
@ChrisJ真正的“神奇”在于'loop()'函数中,它可以重复调用自己所需的次数,并且还可以确保AJAX调用不会全部并行进行。 – Alnitak
发出Ajax请求同步:
所有Ajax请求:
$.ajaxSetup({ async: false });
个人:
$.ajax({
async: false,
.........
});
不,不会*使用同步请求 – Alnitak
的Javascript有一个异步流程。它不会等待上述请求获取da ta从某个地方......相反,它只是连续发射声明。
为了避免这种情况,有3个选项。
- 理想的方法是使1个单HTTP请求到服务器,并获得在JSON阵列的形式的所有数据。这将更加高效,简单和省时,并遵循最佳实践。
进行ajax的异步调用。你会在这个答案jQuery ajax success anonymous function scope得到有关它的好信息。但是,再次推荐回调,不要做异步错误。相反,
.when()
或.then()
更容易..因为最终他们也是回调。递归函数可以帮助你完成这样的任务。这是一种肮脏的方法,因为ES5不允许使用递归函数进行更深入的迭代。但ES6确实允许它进行10000次迭代。但它不是一个好方法。它增加了开销和瓶颈你的页面加载。
我将请求分成块的原因是每个块在数据库表中处理大约2500行。在单个请求中执行此操作时,会导致内存和服务器性能方面的巨大问题,因为一个请求可能导致250,000多个结果行。 该AJAX是相当快速和功能,但刚刚出现问题。 这是否有助于澄清为什么我这样做? –
当然可以。 ! @ChrisJ –
但是.promise()系统肯定会对这样的应用程序有好处。 http://www.htmlgoodies.com/beyond/javascript/making-promises-with-jquery-deferred.html –
AJAX调用是异步的,因此它们不能用在循环结束之前成功(如JavaScript是非阻塞)。事实上你所想要做的是AJAX调用后,不只是循环(这是同步)后进行动作,所以我会或者使用承诺或链接或聚合成功的事件,如以下建议:
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');
}
不幸的是,这仍然不起作用。 '测试'提示将随机出现在结果集内。经过8次迭代测试,它在循环结束前的一个随机点发出警报 –
这是不正确的代码 - 循环内的“i”没有正确绑定到当前迭代计数,当它用于'成功'处理程序。 – Alnitak
这可能是我的错,因为使用php'$ i'作为父迭代,而JS'i'作为我的子迭代,这可能使它看起来像在这种情况下是同一个,抛弃了作者答案 –
看看:[为什么我的变量在函数内部修改后没有改变? - 异步代码引用](http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Andreas
使用承诺。或者对于简单的ajax,使用Callback。 –
您可以对函数使用递归调用,将其添加到$ .ajax的成功参数中。这会按照您希望的顺序加载所有内容。 –