.each()完成后调用jQuery函数
在jQuery中,是否有可能在调用 .each()
(或任何其他types的迭代callback) 完成后调用callback或触发事件 。
例如,我想这个“淡入淡出”来完成
$(parentSelect).nextAll().fadeOut(200, function() { $(this).remove(); });
在做一些计算并在$(parentSelect)
之后插入新的元素之前。 我的计算是不正确的,如果现有的元素仍然是可见的jQuery和睡眠/延迟一些任意时间(每个元素200)似乎是一个脆弱的解决scheme充其量。
我可以很容易.bind()
必要的逻辑到一个事件callback,但我不知道如何干净地调用.trigger()
上面的迭代完成后 。 显然,我不能在迭代中调用触发器,因为它会多次触发。
在$.each()
的情况下,我已经考虑在数据参数的末尾添加一些东西(我会在迭代体中手动查找),但是我讨厌被迫这样做,所以我希望有一些其他优雅的方式来控制迭代callback的stream程。
@电视的答案替代:
var elems = $(parentSelect).nextAll(), count = elems.length; elems.each( function(i) { $(this).fadeOut(200, function() { $(this).remove(); if (!--count) doMyThing(); }); });
请注意.each()
本身是同步的 – 调用.each()
之后的.each()
只有在.each()
调用完成后才会执行。 然而,在.each()
迭代中开始的asynchronous操作当然会以自己的方式继续进行。 这就是问题所在:淡化元素的调用是由定时器驱动的animation,而且这些animation以自己的速度继续。
因此,上面的解决scheme会跟踪有多less元素正在褪色。 每次调用.fadeOut()
都会得到一个完成callback。 当callback注意到通过所有涉及的原始元素进行计数时,可以有把握地确信所有的衰落都已经完成。
这是一个四岁的答案(在这一点上在2014年)。 一个现代化的方式可能会涉及使用延迟/承诺机制,虽然上面是简单的,应该工作得很好。
好的,这可能是事实之后的一小部分,但是.promise()也应该可以实现。
承诺文件
我正在从事一个项目的一个例子:
$( '.panel' ) .fadeOut( 'slow') .promise() .done( function() { $( '#' + target_panel ).fadeIn( 'slow', function() {}); });
🙂
这可能是晚了,但我认为这个代码工作…
$blocks.each(function(i, elm) { $(elm).fadeOut(200, function() { $(elm).remove(); }); }).promise().done( function(){ alert("All was done"); } );
JavaScript同步运行,所以无论你在each()
之后放置什么,在each()
完成之前each()
不会运行。
考虑以下testing:
var count = 0; var array = []; // populate an array with 1,000,000 entries for(var i = 0; i < 1000000; i++) { array.push(i); } // use each to iterate over the array, incrementing count each time $.each(array, function() { count++ }); // the alert won't get called until the 'each' is done // as evidenced by the value of count alert(count);
当警报被调用时,count将等于1000000,因为直到each()
完成后警报才会运行。
我发现了很多处理数组的响应,但没有使用json对象。 我的解决scheme是简单地遍历对象一次递增计数器,然后迭代通过对象执行您的代码时,您可以增加第二个计数器。 然后,您只需将两个计数器进行比较并获得您的解决scheme。 我知道这有点笨重,但我还没有find一个更优雅的解决scheme。 这是我的示例代码:
var flag1 = flag2 = 0; $.each( object, function ( i, v ) { flag1++; }); $.each( object, function ( ky, val ) { /* Your code here */ flag2++; }); if(flag1 === flag2) { your function to call at the end of the iteration }
就像我说的那样,这不是最优雅的,但它的工作原理,它运作良好,我还没有find一个更好的解决scheme。
干杯,JP
如果你愿意做几个步骤,这可能工作。 虽然这取决于animation的整理顺序。 我不认为这应该是一个问题。
var elems = $(parentSelect).nextAll(); var lastID = elems.length - 1; elems.each( function(i) { $(this).fadeOut(200, function() { $(this).remove(); if (i == lastID) { doMyThing(); } }); });
关于什么
$(parentSelect).nextAll().fadeOut(200, function() { $(this).remove(); }).one(function(){ myfunction(); });
你必须排队请求的其余部分才能正常工作。
var elems = $(parentSelect).nextAll(); var lastID = elems.length - 1; elems.each( function(i) { $(this).fadeOut(200, function() { $(this).remove(); if (i == lastID) { $j(this).queue("fx",function(){ doMyThing;}); } }); });
我遇到同样的问题,我解决了像下面的代码的解决scheme:
var drfs = new Array(); var external = $.Deferred(); drfs.push(external.promise()); $('itemSelector').each( function() { //initialize the context for each cycle var t = this; // optional var internal = $.Deferred(); // after the previous deferred operation has been resolved drfs.pop().then( function() { // do stuff of the cycle, optionally using t as this var result; //boolean set by the stuff if ( result ) { internal.resolve(); } else { internal.reject(); } } drfs.push(internal.promise()); }); external.resolve("done"); $.when(drfs).then( function() { // after all each are resolved });
该解决scheme解决了以下问题:使用Deferred对象同步在.each()迭代中启动的asynchronous操作。