5

An example :

var list = readHugeList();

var nextListItem = function() {
    var item = list.pop();

    if (item) {
        setTimeout( nextListItem, 0);
        // ^^^^^^^^ this line
    }
};

How does use of setTimeout prevent potential stackoverflow here? I understand concept of event queue as well as stack, but I'm having difficulty connecting the two.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Abhinav Gauniyal
  • 7,034
  • 7
  • 50
  • 93
  • 6
    If you just called nextListItem from within nextListItem, the stack will grow with each call until you reach the exit criteria (list empty). When you use setTimeout, the outer function will finish and will be removed from the stack, only the inner function call will be on the stack then – devnull69 Jun 02 '16 at 13:15

2 Answers2

6

Set timeout would not cause stack overflow, because it is asynchronous. It will just put the callback to the event queue and not block the execution.

In the first case:

setTimeout just puts the callback to event queue and the parent function exits after without busying the stack.
Even though the timeout is 0 ms, it will be called in the next event loop, thus not blocking the code in execution

var nextListItem = function() {
    var item = list.pop();

    if (item) {
         setTimeout( nextListItem, 0);
    }
};

In the second case:

Parent call the child function putting new entry into stack, even though the parents is not cleared from the stack.
Eventually more recursive calls would blow the stack.

var nextListItem = function() {
        var item = list.pop();
    
        if (item) {        
           nextListItem();
        }
    };
Community
  • 1
  • 1
rishabh dev
  • 1,711
  • 1
  • 15
  • 26
3

Think of setTimeout(, 0) to schedule a function to run after this one terminates. nextListItem() will not be recursively called, but called again by the JS environment.

If you do var r() = function() { r(); }; the function calls itself and will overflow the stack. If you do var r() = function() { setTimeout(r, 0); }; then r() will be scheduled to run after r() terminates and it will run forever.

There is a reason to use setTimeout(, 0) instead of while or for to loop over the list: It allows the browser to process other events before the next call to nextListItem. If the list is long, this avoids blocking the browser for a long time. On the other hand, if nextListItem is manipulating the DOM, it is much slower than doing it in one slew.

sba
  • 1,829
  • 19
  • 27