在 jQuery 中,在调用 .each()
(或任何其他类型的迭代回调)完成后,是否可以调用回调
或触发事件。 比如我想完成这个“淡入淡出”
$(parentSelect).nextAll().fadeOut(200, function() {
$(this).remove();
});
在进行一些计算并在
$(parentSelect)
之后插入 new
元素之前。如果现有元素对 jQuery 仍然可见,并且睡眠/延迟任意时间(每个元素 200)似乎是一个脆弱的解决方案,那么我的计算是不正确的。我可以轻松地
.bind()
事件回调的必要逻辑,但我不确定如何在上述迭代完成后干净地调用
.trigger()
。显然,我无法在迭代内调用触发器,因为它会触发多次。
在$.each()
的情况下,我考虑过在数据参数的末尾添加一些东西(我会在迭代主体中手动查找),但我不想被迫这样做,所以我希望在那里是控制迭代回调流程的其他一些优雅方法。
$blocks.each(function(i, elm) {
$(elm).fadeOut(200, function() {
$(elm).remove();
});
}).promise().done( function(){ alert("All was done"); } );
var elems = $(parentSelect).nextAll(), count = elems.length;
elems.each( function(i) {
$(this).fadeOut(200, function() {
$(this).remove();
if (!--count) doMyThing();
});
});
请注意,
.each()
本身是
同步——调用
.each()
之后的语句仅在.each()
调用完成后才会执行。然而,.each()
迭代中的异步操作started当然会以自己的方式继续。这就是这里的问题:淡入淡出元素的调用是计时器驱动的动画,并且这些动画按照自己的节奏继续。因此,上面的解决方案会跟踪有多少元素正在褪色。每次调用
.fadeOut()
都会得到一个完成回调。当回调注意到它已通过所有涉及的原始元素进行计数时,可以放心地采取一些后续操作,所有的淡入淡出都已完成。
这是一个四年前的答案(2014 年的此时)。执行此操作的现代方法可能涉及使用 Deferred/Promise 机制,尽管上面的方法很简单并且应该可以正常工作。
each()
之后放置的任何内容都将在
each()
完成之前运行。考虑以下测试:
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);
调用警报时,计数将等于 1000000,因为警报在
each()
完成之前不会运行。
$.when(
$.each(yourArray, function (key, value) {
// Do Something in loop here
})
).then(function () {
// After loop ends.
});
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
}
就像我说的,它不是最优雅的,但它有效,而且效果很好,我还没有找到更好的解决方案。
干杯, JP
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;});
}
});
});
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
});
该解决方案解决了以下问题:使用 Deferred 对象来同步 .each() 迭代中启动的异步操作。
从此:
$(".vvp-item-tile").each(function(){
await whatever($(this));
console.log($(this));
});
console.log("for loop is completed"); //Does not wait.
对此:
var arrObj = $(".vvp-item-tile"); //Return an array of object
var obj = null;
for(let i = 0; i < arrObj.length; i++){
obj = $(arrObj[i]);
await whatever(obj);
console.log(obj);
}
console.log("for loop is completed");