how does setTimeout prevent potential stackoverflo

2019-02-26 08:29发布

问题:

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.

回答1:

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();
        }
    };


回答2:

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.

The 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.