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?
The setTimeout() method sets a timer which executes a function or specified piece of code once the timer expires. names. forEach((name) => { setTimeout(() => { display(name); }, 1000); }); But all that happens here is that nothing is displayed for 1000 milliseconds (1 second), then we see the last name again!
It's important to understand that closures are created when functions are created, not when they are invoked. And because a closure was created when this setTimeout function was created, this enables the setTimeout function to access the i variable at whatever time the setTimeout function will run.
forEach() creates closures.
setTimeout function in JavaScript usually takes a callback function as an argument. A callback function is a function that is executed after another function finishes running. In this case, it will run after for loop finishes.
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);
});
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With