Skip the function if executing time too long. JavaScript

In order to know how much time a function takes to execute, you need to execute it and measure. Read about the Halting Problem. Turing basically proves the halting problem unsolvable, which means that there's no programmatic way of determining whether a loop is infinite, or more generally, whether an execution would ever stop.

The issue is that even if you set a threshold, in terms of time, on your function execution, you cannot terminate your function from outside. This way once you get into the infinite loop, you wouldn't be able to terminate it, unless your function internally assumes it can go into an infinite loop, and thus measures its own execution time and terminates if it surpasses it. Even with such an approach, you wouldn't save execution time, as all of your functions would still execute, and some would just terminate after they surpass the provided threshold. This, of course, also assumes that all of the methods you execute are written by you, with the assumptions in mind, and no external methods are used.


setTimeout cannot be used to halt the execution of a function

setTimeout cannot be used to cancel the execution of a function. setTimeout is simply a delay before your function is called. Which simply means, yes you can stop it before it's executed but once it's executed you can't.

Halt by checking the time lapsed (not recommended).

A solution would be to check how much time the function is taking by placing checks a bit everywhere in your function.

function A(mili){
  const end = Date.now() + mili;
  for(let i = 0; i < 10000; i++){
    for(let j = 0; j < 10000; j++){
      if(Date.now() > end){
        console.log(mili + ": Halting A...");
        return;
      }
    }
  }
  
}

A(100); //halted
A(1000); //halted
A(10000); //passed

But this doesn't solve your problem and is not recommended because it requires you to add many "checks" at key points where your function may be taking time too long during execution.

Halt by using function generators

This is assuming you're in a synchronous environement

Function generators is not a perfect solution but it is a better solution.

It requires two easy to understand modifications of your original function.

  1. Add * to your function name
  2. Add yield keyword in key spots in your function that may be deemed "long execution time"

Finally, pass the function you wish to test in some wrapper like the run method provided below.

function* A(){
  for(let i = 0; i < 10000; i++){
    for(let j = 0; j < 1000; j++){
       yield;
    }
  }
  return "some final value";
}

function run(gen, mili){
  const iter = gen();
  const end = Date.now() + mili;
  do {
    const {value,done} = iter.next();
    if(done) return value;
    if(end < Date.now()){
      console.log("Halted function, took longer than " + mili + " miliseconds");
      return null;
    }
  }while(true);
}

console.log("Running...");
const res1 = run(A, 1000);
const res2 = run(A, 5000);
const res3 = run(A, 100);

console.log("run(A,1000) = " + res1); //halted
console.log("run(A,5000) = " + res2); //passed
console.log("run(A,100) = " + res3); //halted