Skip to content
Advertisement

How to pause and resume function execution in javascript

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 ?

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:

  1. Put yield statements in your method, in places where you want to pause it.
  2. Create instance of your generator and write code that will call its .next() method and will handle repeated calls.
  3. 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>
Advertisement