Reputation: 101
Here's the piece of code that I've been testing out to check if I can stop a for loop using setTimeout and clearTimeout. The for loop keeps runs on and on.
var ticket, key;
$(document).on("keydown", function(e){
if (e.key == "m") ticket = setTimeout(runMe,0);
if (e.key == "a") {clearTimeout(ticket); key = "a";}
})
function runMe(){
for (var i=0; i < 1000000; i++){
if (key == "a") break; // doesn't work
myFunct(i);
}
}
function myFunct(i){
console.log(i);
}
var ticket, key, i=0;
$(document).on("keydown", function(e){
if (e.key == "m") ticket = setInterval(runMe,0,i++);
if (e.key == "a") {clearInterval(ticket); key = "a";}
})
function runMe(i){
console.log(i);
//myFunct(i);
}
function myFunct(i){
console.log(i);
}
Upvotes: 0
Views: 510
Reputation: 150040
JavaScript is single-threaded, so your key handler will not run until after the runMe()
function has run till completion.
You can instead build an asynchronous looping function using setTimeout()
(or setInterval()
), so that other code - like a key handler - gets a chance to run in between iterations of the "loop".
I'd suggest encapsulating the loop-handling code inside the runMe()
function and have runMe()
return a function that can be called to stop the current loop. That way you can easily have multiple, unrelated loops going at the same time and stop them independently - you'd need to keep track of each, and I have not shown that in the code below, but it's not much more than what I have shown. (If you make the loop counter a single global variable then obviously you can't have separate concurrent loops.)
var stopLoop;
$(document).on("keydown", function(e){
if (e.key == "m") stopLoop = runMe();
if (e.key == "a") stopLoop();
});
function runMe(){
var i=0;
var last=300; // I've used a smaller number so that you don't have to
// wait too long to see see that it stops by itself if
// you don't press "a" in the meantime
var stop = false;
(function looper() {
myFunct(i);
if (++i < last && !stop)
setTimeout(looper, 5);
})();
return function() { stop = true; }
}
function myFunct(i){
console.log(i);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 781130
You can't stop synchronous code with asynchronous code, because the async code isn't executed until you return to the main event loop.
If you want to run something repeatedly, use setInterval
, then clear it when the event occurs.
var counter = 0;
var interval;
function runMe() {
if (counter == 1000) {
clearInterval(interval);
} else {
counter++;
$("#output").text(counter);
}
}
$(document).on("keydown", function(e) {
if (e.key == 'm') {
interval = setInterval(runMe, 10);
} else if (e.key == 'a') {
clearInterval(interval);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
Upvotes: 1
Reputation: 7197
Maybe you could use a webworker to run the for loop code, then use terminate() to halt the loop.
// forloop.js
for (var i=0; i < 1000000; i++){
myFunct(i);
}
function myFunct(i){
console.log(i);
}
// index.js
var myWorker;
$(document).on("keydown", function(e){
if (e.key == "m") myWorker = new Worker('forloop.js');
if (e.key == "a") {myWorker.terminate();}
})
Note: code is not tested, only to give you the rough idea
Upvotes: 1