views:

1067

answers:

2

Hello,

My question is the following:

What is the best way for looping some json array too show some data with like a one second delay.

The one below does not work, because it only shows one message once instead of 4

jQuery.each(data.user, function(index, itemData) { 


    timerid = setTimeout(function(){showMessage(itemData);}, 1000);
                   });

function showMessage(message){
    $('#status_info').html(message);
    clearTimeout(timerid);
}

thanks, Richard

+3  A: 

Try setInterval instead:

var i = 0;
window.setInterval(function() {
    $('#status_info').html(data.user[i++]);
    i = i == data.user.length ? 0 : i; // loops the interval
}, 1000);
David
Thanks, is it neccasary to use window or could that be a variable too or nothing? I actually like this one better because I can understand the syntax. But the one from @Alex maybe has some more advantages?
Richard
It depends. setInterval might be a better fit for this task, but it's also a matter of preference. You can also store the interval in a variable and then clear it if you need to stop the interval. Standard is to use window.setInterval() but you can leave out the window part (not recommended). See: https://developer.mozilla.org/en/DOM/window.setInterval
David
+2  A: 

If you want to avoid a setInterval and just bound the calls to the length of your list, you can create a self-executing function that saves your current index instead of using the one from the closure. The variable from the closure will end up always being the last element in your each loop, since the loop will finish long before the variable in your setTimeout function is read.

You are also calling the clearTimeout function, which doesn't make a whole lot of sense to me in this context.

On top of that, all of your setTimeouts are going to be called nearly at the same time. This would result in all the values flashing on the screen milliseconds apart (or too fast to see in some cases). A loop isn't really appropriate here, because the setTimeout function is asynchronous. A system of callbacks is best for a finite number of runs, and a setInterval system is best for an unknown amount of runs. To me your number of runs should be the number of elements in your jQuery object (the ones that are currently going through your $.each())

I would suggest that you do something like the following generalized example of your question (generalized since I don't have access to your dom).

function showMessage(message){
  $('body').html(message);
}

var itemData = [1,2,3,4];

var i = 0;

function idTimer(list, i) {
  if (!(i >= 0)) {
     i= 0;
  }
  setTimeout((function(msg){
    i++;
    return function(){
      if(i < list.length){
        idTimer(list, i);
      }
      showMessage(msg);
    }
  })(list[i]), 1000);
}

idTimer(itemData);

A live demo of this code can be found at: http://jsbin.com/ifuqo

Alex Sexton
Thank you, I just cameup with this myself too. Although not with the callbacks, looks interesting. I have set a global counter and an array. and in the ajax function I push data to the array and set a setinterval() if it received any data.
Richard
It's quite difficult to follow that syntax, but I will check out that link.
Richard