I have this function:
const BFS = (graph, start) => { let queue = [] queue.push(start) let visited = [] visited[start] = true while (queue.lenght > 0) { let node = queue.shift() for (var i=1; i<graph[node].length; i++) { if (graph[node][i] && !visited[i]) { visited[i] = true queue.push(i) } } } }
What I want is to have a button that when I press it, It stops the execution of the function, and if I press it again, it resumes the execution from the same place it stopped on.
Is that possible ? and if so, how to do it ?
Advertisement
Answer
Other solution with generator functions, read about this feature on MDN
Note, that here we can proceed further one step at a time!
General idea:
- Put
yield
statements in your method, in places where you want to pause it. - Create instance of your generator and write code that will call its
.next()
method and will handle repeated calls. - Note, that you can get values from generator and also pass in with
.next()
method.
// generator function that we want to stop/continue in the middle function* stoppableMethod() { // here is the implementation of the algorithm // that we want to control let i = 0; while (true) { // note that yield is inside infinite loop! yield i; i += 1; } } const generatorInstance = stoppableMethod(); // tick generator and perform update of the indicator const nextStep = () => { const { value } = generatorInstance.next(); document.getElementById("indicator").innerHTML = value; } // state to keep track of the setInterval id const state = { timeoutId: 0, } // start method progression const start = () => { // do not start interval if there is already an interval // running if (state.timeoutId === 0) { state.timeoutId = setInterval(() => nextStep(), 1000) } } // clear timeout to stop auto porgress const stop = () => { clearTimeout(state.timeoutId); state.timeoutId = 0; } // tick further one step const stepForward = () => nextStep()
<button onclick="start()">start</button> <button onclick="stop()">pause</button> <button onclick="nextStep()">one step forward</button> <div id="indicator">0</div>