swastican
swastican

Reputation: 255

achieve recursion in javascript

I came from c++ background, so am not much clear on callback mechanisms. Getting confused with java-script to achieve recursion. Someone please help.

This is what i want to achieve.

Method 1(on success - call Method2);
Method 2(on success - call Method3);
Method 3(on success - call Method1)

Here is my code.

function Method1(val1, val2, callback) {
   console.log('Method1' + val1);
   callback(val1, Method3);
}

function Method2(val1, fn) {
  console.log('Method2 ' + val1);
  val1++;
  fn(val1);
}

function Method3(val){
    console.log('Method3 ' + val);
    val++;
    if(val > 1000)  process.exit(0);
    else {
        Method1(val,2, Method2);
    }
}

Method1(1,2,Method2);

Once i run this it throws RangeError: Maximum call stack size exceeded error. How to achieve recursion in javascript?

Edit: I am writing a webcrawler. This is what i wanted to achieve.

1. Get the URL to be crawled.
2. Store the content(webpage) in a file. 
3. Parse the content. Get all the links in the file. 
4. call step 2 for each link in the content.

This can be achieved in recursion only. I understood there has to be end point/exit point. Here my exit point could be once i parse all the weblinks. it should exit.

Upvotes: 0

Views: 239

Answers (4)

swastican
swastican

Reputation: 255

It can be achieved by setImmediate or setTimeout or process.nextTick(nodejs) functions. The efficient way is setImmediate. Reasons given in these below links.

Setimmdiate API: http://nodejs.org/api/timers.html#timers_setimmediate_callback_arg
SetImmediate vs nextTick(SO) : setImmediate vs. nextTick
Explanation 1 : http://www.nczonline.net/blog/2013/07/09/the-case-for-setimmediate/
Explanation 2 : http://howtonode.org/understanding-process-next-tick

SetImmediate is not supported in some browsers as per my knowledge. It is supported only in IE10 as of now. In server-side, nodejs supports those apis.

Upvotes: 0

thgaskell
thgaskell

Reputation: 13226

Javascript doesn't support tail call optimization. Everything is just pushed onto the stack, but doesn't pop off until the end case is reached.

You're maxing out the stack size before the end condition is met.

is there any way to overcome that ?

There are various approaches, but I think the simplest would be set use setTimeout to call your function with its parameters at a later time.


For example:

function count(n, end) {
    console.log(n);
    if (n < end) {
        count(n+1, end);
    }
}
count(0, 100000) // More than enough to exceed the stack limit

This will try to print out all the numbers from 0 to 100000, but it hit the max stack size before it reaches the end.


So instead of calling it directly, you can defer the time of execution by passing it into the setTimeout function, which will take function and it's parameters and run it at a later time. An added benefit of using setTimeout is that the calls will be asynchronous, which means other code can run in the meantime.

function count(n, end) {
    console.log(from);
    if (n < end) {
        setTimeout(count, 0, n+1, end);
    }
}
count(0, 100000) // More than enough to exceed the stack limit, but it will run!

More on how the scheduling works: http://ejohn.org/blog/how-javascript-timers-work/

Upvotes: 1

Hariharan
Hariharan

Reputation: 3263

function Method1(<params>){
   // condition
   if(<params>){
      Method2(<params>);
   }else{
      return;
   }

}

function Method2(<params>){
   // condition
    if(<params>){
      Method3(<params>);
   }else{
      return;
   }
}

function Method3(<params>){
   // condition
    if(<params>){
      Method1(<params>);
   }else{
      return;
   }
}

Method1(<params>);

Note: It require some condition to break the recursion loop, else it wont end the loop.

Upvotes: 0

user1021726
user1021726

Reputation: 648

You need to say when to stop, or else it will just keep on calling each method, resulting in your error.

Upvotes: 2

Related Questions