Do all timers created in the loop (with setTimeout) work at the same time?

Can someone explain why I cannot get the desired delay between each request?
They all happen at once.

$(window).load(function(){ $('a[href]').each(function(){ var linkk = $(this) var linkkhref = linkk.attr('href'); window.setTimeout(function(){ conectar('HEAD', linkkhref, resp) }, 2000) function conectar(metodo, endereco, resposta, corpo) { callback = function(xhr) { resposta(xhr) }; GM_xmlhttpRequest({ "method" : metodo, "url" : endereco, "onerror" : callback, "onload" : callback, "headers" : {'Content-Type':'application/x-www-form-urlencoded'}, "data" : corpo }); }; function resp(responseDetails) { // my response code here }; }); }); 

I know im using a special Greasemonkey function, but the question is about javascript.
No GM knowledge required. :)

0
javascript
source share
3 answers

The loop starts instantly and delays any execution of the conectar function for 2000 ms from the time code.

For a simple case, I would use:

 $('a[href]').each(function(idx){ ... window.setTimeout(function(){ conectar('HEAD', linkkhref, resp) }, idx*2000) 
+4
source share

Becase setTimeout for all links is called immediately. If you want to delay the call, you need to do something like this:

  var delay = 2000; $('a[href]').each(function(){ var linkk = $(this) var linkkhref = linkk.attr('href'); window.setTimeout(function(){ conectar('HEAD', linkkhref, resp) }, delay); delay += 2000; .... 
+3
source share

As Eugene said, this is because setTimeouts happen all at once. Since you are using jQuery, one thing you can do is use jQuery Deferred to run all the calls in the sequence:

 $(function() { // dfd is our "master" deferred, which we will use to pipe the requests, one at a time var dfd = $.Deferred(); // set the deferred to resolve in 2 seconds, which will start the pipeline window.setTimeout(dfd.resolve, 2000); $('a[href]').each(function() { var linkk = $(this); var href = linkk.attr('href'); var req = conectar(...) // replace the master deferred object with one that pipes into the next request dfd = dfd.pipe(req); }); dfd.done(function() { alert("All requests completed!") }); }); 

Of course, if all you care about is starting X seconds after each other, then the rest of the answers will work fine. This method will allow you to effectively "chain" each of them so that the next one starts as soon as the previous one is completed, and also allows you to signal when they are all done (using dfd.done ).

+2
source share

All Articles