Delay JavaScript's function execution
Asked Answered
P

4

8

I have a JQuery's .each loop that calls a function with a parameter per iteration, is there a way to delay this function call? I have tried setTimeout as in the following but this does not work as the function gets executed immediately.

$.each(myArray, function (j, dataitem)
{
     setTimeout(function () { showDetails(dataitem) }, 300);
});

function showDetails(dataitem)
{
...
}

Array size is roughly 20, What I'm trying to do is to distribute function calls over a certain time frame instead of immediately, any idea how to achieve this? I'm prepared to rewrite and restructure how functions get called to get this done, any help would be appreciated.

Pew answered 20/3, 2011 at 22:50 Comment(1)
The execution is definitely deferred. But the loop is not, i.e. all 20 setTimouts are more or less called at once. Do you want to call the showDetail functions one after another? I mean, the first after 300ms, the second after 600ms, etc.Alanna
V
10

You could use the index of the array to calculate the interval dynamically:

$.each(myArray, function (j, dataitem) {
    window.setTimeout(function () { 
        showDetails(dataitem) 
    }, (j + 1) * 300);
});
Velocipede answered 20/3, 2011 at 22:58 Comment(4)
Now that I've re-read the question, this sounds like what the question asker is trying to do. +1Liftoff
Is the window. prefix really needed? I don't think that anyone would ever overshadow the setTimeout name.Shrapnel
@Šime Vidas, I prefer to always use proper scoping. It's just good practice.Velocipede
Do you do it for all properties of the window object (like window.parseInt, window.console.log, window.document.getElementById, etc.)?Shrapnel
B
2

You execute them all after 300 milliseconds. Instead, try something like this:

window.setTimeout(function () { showDetails(dataitem) }, (j + 1) * 300);

Edit: instead of creating 20 timers at once I think it's better to do it one by one. Function should be:

function showDetails(index)
{
   if (index >= myArray.length)
      return false;
   var dataItem = myArray[index];
   //code here......
   //code here......
   //code here......
   windows.setTimeout(function() { showDetails(index + 1); }, 300);
}

And first call can be:

$(document).ready(function() {
{
   showDetails(0);
});

This assume myArray is plain global array, and will handle one item and only then call the next item with delay.

Bloodletting answered 20/3, 2011 at 22:56 Comment(1)
Thank you, I have tried this and it works, I have chosen the first answer though as its easier for me to read in the code. +1 :)Pew
L
2

Take a look at jQuery.queue([ queueName ], callback( next )). This allows you to queue functions up to be called and is what jQuery's animation effects use internally.

It sounds like you would like to implement a queue, although it is not entirely clear you intentions for doing so.

EDIT: re-reading your question, I think other answers better match what you are after, however I thought that I would show you an example of how to achieve delayed function execution with a custom queue.

An example of how you could use a queue.

var myArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
    output = $('#output');

// set the queue up
$.each(myArray, function (j, dataitem) {
    output.queue('queue', function(next) {
        var that = this;
        showDetails(dataitem);  
        window.setTimeout(next,300);
    });
});

// start the queue running.
output.dequeue('queue');

function showDetails(dataitem) {
    output.append('<div>' + dataitem + '</div>');
}
Liftoff answered 20/3, 2011 at 22:57 Comment(1)
This is actually useful to know. +1 :)Pew
J
0

Just don't use $.each, but something like:

var data = [1, 2, 3, 4, 5];

function showDetails(values, delay) {
  console.log(values.shift()); //show the value
  if (values.length) {
    setTimeout(function() {showDetails(values, delay); }, delay); //schedule next elem
  }
}

showDetails(data.slice(0), 300); //dont forget the slice, call-by-reference
Jailbreak answered 20/3, 2011 at 23:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.