Javascript setTimeout in foreach: need help creati

2019-04-24 09:17发布

问题:

I have this function

notes.forEach(function(note) {          
    setTimeout(function() {
        playNote(note);
    }, 1000);
});

This doesn't work. It plays all the notes at the same time, instead of playing them sequentially with a 1 second gap in between. It looks like I need to have a closure here to make this work. Could someone help me fix this function so it would play the note with the delay between each note?

回答1:

because all timeouts are set at the same time...

Do something like this:

playAllNotes(0);
function playAllNotes(index) {
    if(notes.length > index) {
        setTimeout(function() {
            playNote(notes[index]);
            playAllNotes(++index);
        }, 1000);
    }
}


回答2:

There are two ways to do this:

1) Have a function that grabs one note every second until there are no more notes:

var interval = setInterval(function() {
  playNote(notes.shift()); // changes the notes array!
  if (!notes.length) clearInterval(interval);
}, 1000);

2) Start all the timers at the same time with different delays:

notes.forEach(function(note, index) {
  setTimeout(playNote.bind(null, note), index*1000);
});


回答3:

You can use a counter, it's tricky but worth it if you are working with objects:

counter = 0;
$.each(object, function(index,item){
  counter++;
  var localCounter = counter;
  setTimeout(function{
   console.log('something')
  }, counter * 1000) // change one to number of milliseconds you need
})

First counter is global, so if we don't user var localCounter we would execute all timeouts at the same time.