Best way to insert a 'pause' in a .each enumeration
What is the best/recommended manner in which to insert a 'pause' with each enumeration over a set of elements using the jQuery '.each()'?
$( '.someClass' ).each( function() {
$( this ).trigger( 'click' ); //fire some request that appends a new div on the body
//wait for div to be appended to the DOM. perhaps use the pause here
//exec开发者_StackOverflow社区ute code once the div has been appended
});
Technically, you can't do this as you have modeled in your code, since JavaScript is single-threaded, and usually runs on the browser (or tab) UI thread -- any sleep/delay will block the browser from redrawing the page and will also prevent user interaction with the page.
You need to arrange for the browser to invoke your code periodically. Something like this will do the trick:
var objects = $.makeArray($( '.someClass' ));
var callback;
callback = function() {
var item = objects.shift();
// Do something with item.
if (objects.length != 0) {
setTimeout(callback, 5000);
}
}
setTimeout(callback, 5000);
See an example.
This solution assumes that you want each item to be processed 5 seconds from the time that the last item finished processing. This means that:
- If you do
confirm()
or something while processing each item, the next item will be processed 5 seconds from the time that the user closes the dialog. - The total execution time will be (5000N + T) where N is the number of items in the initial list, and T is the total time it takes to process each item.
Here's a function you can use that encapsulates this functionality:
jQuery.eachWithDelay = function(sequence, delay, callback) {
var objects = jQuery.makeArray(sequence);
if (objects.length == 0) {
return;
}
var f;
f = function() {
var item = objects.shift();
if (callback(item) && objects.length != 0) {
setTimeout(f, delay);
}
};
setTimeout(f, delay);
};
Called like:
$.eachWithDelay($('.someClass'), 5000, function(item) {
// Do something with item
return true; // Return true to continue iterating, or false to stop.
});
See the updated fiddle.
If you must use .each
for some reason, then this will get you pretty close, provided you're not doing a ton of work inside each iteration:
var i = 0;
$( '.someClass' ).each( function() {
setTimeout((function (el) {
// do something with 'el'
})(this), i * 5000);
i += 1;
});
But it would be more correct (given the wording of your question) to do something like this:
(function() {
var arr = $('.someclass'),
i = 0,
fn = function() {
var el = arr[i];
// do something with 'el'
i += 1;
if (i < arr.length) {
setTimeout(fn, 5000);
}
};
fn();
})();
There is no good way to put a delay like that in the middle of a javascript function.
To legitimately delay for 5 seconds before the next increment of work, you need to acquire the data you need for the job, break the work into small chunks, set a 5 second timer and do one chunk of the work on each timer tick.
Here's a working example of one way to do that: http://jsfiddle.net/jfriend00/tgBYk/
var objList = $('.someClass');
var cntr = 0;
var timeDelay = 5000;
function doNextIteration() {
$(objList[cntr++]).html(cntr); // your code here: This is the progress I'm showing in my demo
if (cntr < objList.length) {
setTimeout(doNextIteration, timeDelay);
}
}
if (objList.length > 0) {
doNextIteration();
}
if you have the html
like
<div class="someClass">google</div>
<div class="someClass">facebook</div>
<div class="someClass">ARPANET</div>
wrap it in $(document).ready()
jsfiddle does it automatically
$(".someClass").each(function(i){
$(this).delay(i+"1000").fadeOut("slow");
});
here is the fiddle http://jsfiddle.net/J6Mw6/1/
you can set the time of your choice
or maybe this can help according to your edited question
http://jsfiddle.net/J6Mw6/2/
Since we're just throwing answers around it seems; heres mine. No each?
function doTheDo(els) {
if(els.length == 0) return; $(els.shift()).click(); setTimeout(doTheDo, 5000, els);
}
doTheDo($( '#errors li' ).toArray());
setTimeout(yourFunction(),5000);
would probably be the thing you want. But remember that this function will execute yourFunction()
after 5s. If there is code after your setTimeout then it will still execute right away, so it depends on what you want to do. If you really want to halt all execution of all of your code, then it's a harder problem to solve. You can take a look at this document for some proposed solutions/functions. But with JavaScript it's hard to completely halt your execution without completely locking up your CPU.
精彩评论