I need to break from a for loop on a given UI event. I worked out the approach shown below; however, it is unpredictable and I have a sense that this is not the right way to do this.
In this minimal example I break from the for loop when the user clicks the document by awaiting a setTimeout at each iteration of the for loop. This await allows for stop
to be set to true
, which causes the break to happen.
This for loop just logs a zero to the console. A more practical use case may be to stop adding list elements to an unordered list given a UI event e.g., the keypress event.
let zeros = new Array(10000).fill(0);
(async () => {
let stop = false;
document.addEventListener('click', async ()=>{
console.log('click');
stop = true;
await new Promise((r)=>setTimeout(r, 100)); //2
stop = false;
});
for (let zero of zeros) {
await new Promise((r)=>setTimeout(r, 100)); //1
if (stop) {
break;
}
console.log(zero);
}
})();
CodePudding user response:
you can accomplish this by adding your function to the event loop instead of using a for loop
using your example, a solution could look like this:
let zeroes = new Array(10000).fill(0);
let index = 0
let stop = false
document.addEventListener('click', async ()=>{
console.log('click');
stop = true;
});
function loopOverArray(index){
if(!stop && index < zeroes.length){
requestAnimationFrame(loopOverArray)
}
console.log(zeroes[index])
index
}
CodePudding user response:
Just use setInterval
. No need to complicate things with await
and setTimeout
. Not sure why you're setting stop
back to false after setting it to true though...
let stop = false;
document.addEventListener('click', () => (stop = true));
const id = setInterval(() => {
console.log('running');
if (stop) {
console.log('stopped');
clearInterval(id);
}
});
To do this while iterating through an array:
const arr = new Array(1000).fill(0);
let stop = false;
document.addEventListener('click', () => (stop = true));
let index = 0;
const id = setInterval(() => {
console.log(arr[index ]);
if (stop || index === arr.length) {
console.log('stopped');
clearInterval(id);
}
});