JavaScript-рекурсия: превышен максимальный размер стека вызовов

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

Я получаю сообщение об ошибке «Превышен максимальный размер стека вызовов», и я понимаю проблему, но я просто не знаю, как ее решить ... Я нашел три возможных решения для решения проблем рекурсии в целом:

Изменить рекурсию на итерациюиспользованиемемоизацииИспользовать SetTimeout

Но я думаю, что я не могу использовать ни один из них:

Я не могу реализовать итерацию из-за неизвестного количества необходимых операцийЯ не очень хорошо понимаю запоминание, но думаю, что оно тоже не подходит (или, может быть, я ошибаюсь, и кто-то может сказать мне по-другому?)Я не могу использовать SetTimeout, потому что он должен блокировать вызовы функций в этой конкретной анимации.

Как мне решить эту проблему?

// Pushes circles aside when some other circle leans on these circles (on zoom in)
var moveCirclesAside = function(circle1, circleToSkip, groupOfMoves) {
    var count = circles.length;
    for (var i = 0; i < count; i++) {

        // Skip the same circle
        if (i == circle1.i) {
            continue;
        }

        // Also skip the circle which was intended not to move any further
        if (circleToSkip != null && i == circleToSkip.i) {
            continue;
        }

        // Get second circle
        var circle2 = circles[i];

        // Calculate a distance between two circles
        var dx = circle2.x - circle1.x;
        var dy = circle2.y - circle1.y;
        var distance = Math.sqrt((dx * dx) + (dy * dy));

        // If circles already collided need to do some moving...
        if (distance <= circle1.r + circle2.r + OD.config.circleSpacing) {

            // Get collision angles
            var angle = Math.atan2(dy, dx);
            var sine = Math.sin(angle);
            var cosine = Math.cos(angle);

            // Some circle position calculation
            var x = OD.config.circleSpacing;
            var xb = x + (circle1.r + circle2.r);
            var yb = dy * cosine - dx * sine;

            // Save each state (move) of any circle to the stack for later rollback of the movement
            groupOfMoves.push(copyCircleByVal(circle2));

            // Move the circle
            circle2.x = circle1.x + (xb * cosine - yb * sine);
            circle2.y = circle1.y + (yb * cosine + xb * sine);

            // Make sure that circle won't go anywhere out of the canvas
            adjustCircleByBoundary(circle2);

            // If moved circle leans against some other circles make sure that they are moved accordingly
            // And such related moves must be grouped for correct rolback of moves later - so we pass 'groupOfMoves' var
            moveCirclesAside(circle2, circle1, groupOfMoves);
        }
    }
};

Ответы на вопрос(4)

Ваш ответ на вопрос