Максимальное количество вызовов не превышает определенный код внутри функции в NodeJS - PullRequest
0 голосов
/ 04 февраля 2019

Мой вопрос довольно прост.Я просто не понимаю такого поведения, которое происходит в моей среде NodeJS.

Приведенный ниже код не превышает максимальный стек вызовов функций:

const loop = (i, maxI) => {
    if (i === maxI) {
        return;
    }

    if (i % 1000 === 0) {
        console.log(i);
    } 

    return loop(i + 1, maxI)
}

if (!module.parent) {
    loop(0, 100000000000000000);
}

Однако приведенный ниже код каким-то образом разрушает стек?

const loop = (i, maxI) => {
    if (i === maxI) {
        return;
    }

    if (i % 10000 === 0) {
        console.log(i);
    } 

    return loop(i + 1, maxI)
}

if (!module.parent) {
    loop(0, 100000000000000000);
}

Даже это приводит кStack Up:

const loop = (i, maxI) => {
    if (i === maxI) {
        return;
    }

    return loop(i + 1, maxI)
}

if (!module.parent) {
    loop(0, 100000000000000000);
}

Я использую NodeJS v10.15.1 в Windows 10. Я предполагаю, что хвостовая рекурсия не оптимизирована в NodeJS, но как этот конкретный сценарий не приводит к взрыву стека вызовов функций?

1 Ответ

0 голосов
/ 04 февраля 2019

Это происходит потому, что у JS есть стек, в котором он ставит в очередь вызовы функций, и существует предел памяти, назначенной этому стеку.

Вы должны заключить рекурсивный вызов функции в setTimeout, setImmediateили process.nextTick, чтобы дать возможность node.js очистить стек.Если вы этого не сделаете и существует много циклов без какого-либо реального асинхронного вызова функции или если вы не ждете обратного вызова, ваш RangeError: Превышен максимальный размер стека вызовов будет неизбежен.

При этом сейчасВ вашем первом коде вы выполняете

i % 1000

, что сравнительно легче, чем операция, выполняемая во втором коде

i % 10000

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

Пожалуйста, попробуйте поместить оператор log в третий фрагмент кода и попробуйте его.Это прояснит вам ситуацию.

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