что происходит со стеком при использовании process.nextTick - PullRequest
0 голосов
/ 18 октября 2019

Я вычисляю некоторую тяжелую рекурсивную функцию (скажем, Фибоначчи для следующего кода). У меня есть две версии: - первая, ванильная рекурсивная (раскомментирующая "if (false)") - вторая, использующая process.nextTickкаждые 5 вызовов для запуска другого кода (без комментария «if (n% 5 == 0)»)

, выполняющегося первым, я получаю «RangeError: Превышен максимальный размер стека вызовов» при запуске второгоодин дает мне хороший "196418"

вот код. Не могли бы вы рассказать мне, что происходит, потому что я не могу поверить, что process.nextTick очищает стек.

'use strict';

function fibo_cb( n, cb ){ fibo_rec( n, (res) => cb( res ) ); }

function fibo_rec( n, ret ){
    if( n<2 ){
        ret( 1 );
    } else {
        let rr = (res_1) => { return (res_2) => ret(res_1+res_2) };
        let r = (res_1) => fibo_rec( n-2, rr(res_1) );
        //if(false){ //no tick
        if(n%5==0){ //do tick, once every 5
            process.nextTick( () => fibo_rec( n-1, r ) );
        } else {
            fibo_rec( n-1, r );
        }
    }
}

fibo_cb( 26, console.log );

1 Ответ

1 голос
/ 18 октября 2019

Код JavaScript выполняется путем помещения всего кода в стек вызовов с помощью создания областей на уровне функций. Поскольку JavaScript является однопоточным (кроме асинхронных задач), начиная с глобального уровня, каждая область помещается в стек вызовов один за другим, пока не достигнет всех функций. Как только функция завершена, она извлекается из стека вызовов.

В случае рекурсивных функций для каждого рекурсивного вызова функция помещается в стек вызовов. Таким образом, при большом количестве рекурсивных вызовов стек вызовов заполняется, поскольку установлен максимальный предел для стека вызовов .

Любая асинхронная задача, запланированная с использованием process.nextTick, ожидает, пока стек вызовов не станет пустыми берет каждый обратный вызов из очереди событий и переводит его в стек вызовов . Это происходит несколько раз, пока все рекурсивные обратные вызовы не будут завершены.

Поскольку стек вызовов очищается каждый раз, когда "RangeError: превышен максимальный размер стека вызовов" наблюдается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...