3

I am working on small part of calculation code. I need to identify whenever recursive occur in javascript/jQuery and i need to terminate that recursive.

Is there any api to support this in javascript/jQuery?

noseratio
  • 59,932
  • 34
  • 208
  • 486
Pyare
  • 671
  • 2
  • 11
  • 32
  • A hint: js is single threaded – zerkms Feb 04 '14 at 04:40
  • Do you mean to stop infinite recursion? – Salman A Feb 04 '14 at 04:42
  • A browser will do that :-D – zerkms Feb 04 '14 at 04:48
  • @zerkms - But JavaScript can also be multi-thread (Workers) – Derek 朕會功夫 Feb 04 '14 at 04:49
  • @Derek 朕會功夫: it's just an attempt to be so. You cannot run an arbitrary code from it. And you don't have much control over it. – zerkms Feb 04 '14 at 04:51
  • http://stackoverflow.com/questions/9619977/detect-infinite-recursion – Deepak Ingole Feb 04 '14 at 04:57
  • Can you give an example of how you would expect such a function to be called? It might be possible with `fn.toString()` hacks but I doubt theyd every be justifiable – megawac Feb 04 '14 at 05:19
  • @Derek朕會功夫 - yes web workers can be multi-threaded, but they cannot share any common JS variables or even code instances (they have to load their own code) with other threads (each thread gets it's own JS state) so thus, it's pretty hard to see how they could interfere with each other. – jfriend00 Feb 04 '14 at 05:47
  • @jfriend00 - They don't share variables, but they pass data and workers can set variables' value after finishing calculator, without halting the main script. – Derek 朕會功夫 Feb 04 '14 at 06:29
  • @Derek朕會功夫 - The only way they can share data is via messaging and messaging is NOT multi-threaded. The main script MUST be finished executing before any incoming messages are processed. The main script cannot be interrupted by messaging from a webworker. Workers can't set any variables that the main script can see. Workers can't access the DOM in any way. WebWorkers have been very, very carefully thought out such that they cannot introduce threading issues in the main thread. – jfriend00 Feb 04 '14 at 06:44
  • @jfriend00 - Why must the main script be finished executing before accepting messages from the worker? I thought asynchronous scripts in JavaScript work like this: Imagine there's an infinite loop and a listener. As the listener receive a message from the worker, the loop will be paused and it will start executing code inside the listener. It's like a shuffled deck of cards. – Derek 朕會功夫 Feb 04 '14 at 06:54
  • @Derek朕會功夫 - because the message is delivered via an event listener and events are ONLY processed when the main thread is not executing. Internally, in the JS engine when the main thread finishes executing, it looks in the event queue to see if there are any events that need triggering. If there is an event it is triggered then. If an event occurs while the main thread is executing, it just goes in the queue and is not processed until the main thread is done. – jfriend00 Feb 04 '14 at 06:56
  • @Derek朕會功夫 - See this post for info on how the event queue works: http://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background/7575649#7575649. – jfriend00 Feb 04 '14 at 06:59
  • @jfriend00 - Okay I just [tested](http://jsfiddle.net/DerekL/h2gKL/) and you are absolutely correct. I really thought the output would be `a` and `b` alternating, but I think mixed JavaScript up with other languages. Thanks for teaching me something new. – Derek 朕會功夫 Feb 04 '14 at 07:02

2 Answers2

5

You could implement your own recursive protection. There is nothing built into jQuery that would natively support preventing recursion.

function myFunc(arg) {
    // if this function already executing and this is recursive call
    // then just return (don't allow recursive call)
    if (myFunc.in) {
        return;
    }

    // set flag that we're in this function
    myFunc.in = true;

    // put your function's code here


    // clear flag that we're in this function
    myFunc.in = false;

}

myFunc.in = false;

You could also turn the boolean into a counter and allow recursion only up to a certain number of levels.

FYI, because JS is single threaded, this should only be an issue that might need protection if your function takes some sort of callback from code that isn't yours. If it's all your own code, then you should just make sure your own code won't cause this sort of problem.


Here's a little more foolproof version that protects the counter in a closure so it can't be manipulated outside the function:

 var myFunc = (function() {
     var inCntr = 0;
     return function(args) {
         // protect against recursion
         if (inCntr !== 0) {
             return;
         }
         ++inCntr;

         try {

             // put your function's code here

         } finally {
             --inCntr;
         }

     }
 })();

Note: this uses a try/finally block so even if your code or any code you call throws an exception the counter is still cleared (so it never gets stuck).

jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

Another dodgy trick. If you use something like .bind(this) for recursion or if you use arrow function, it won't work.

boom();

function boom () {
  if(arguments.callee === arguments.callee.caller) {
    console.log('no recursion will happen');
    return;
  }
  boom();
}

Simple solution could be a flag in a parameter

boom2();

function boom2 (calledRecursively) {
  if(calledRecursively) {
    console.log('no recursion will happen');
    return;
  }
  boom2(true);
}
KasRoudra
  • 315
  • 4
  • 8
Pawel
  • 16,093
  • 5
  • 70
  • 73