JavaScript 递归:超出最大调用堆栈大小 [英] JavaScript recursion: Maximum call stack size exceeded

查看:87
本文介绍了JavaScript 递归:超出最大调用堆栈大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个递归函数可以在画布上移动一些圆圈.覆盖的圆圈被放大(放大),所有其他圆圈被推开.推动的圆圈推动其他圆圈,依此类推,直到缩放完成.

I have a recursive function for moving some circles on a canvas. Overed circle is enlarged (zoom in) and all the other circles is pushed away. Pushed circles push other circles and so on until zooming is complete.

我收到一个错误超出最大调用堆栈大小",我明白这个问题,但我就是不知道如何解决它...我找到了解决递归问题的三种可能的解决方案:

I get an error "Maximum call stack size exceeded", and I understand the problem, but I just don't know how to solve it... I found three possible solutions for solving recursion problems in general:

  1. 将递归改为迭代
  2. 使用备忘录
  3. 使用 SetTimeout

但我认为我不能使用它们:

But I think that I can use none of them:

  1. 由于需要的操作数量未知,我无法实现迭代
  2. 我不太了解记忆,但我认为它也不适合(或者我可能错了,有人可能会以不同的方式告诉我?)
  3. 我不能使用 SetTimeout,因为它应该在这个特定的动画中阻塞函数调用.

我该如何解决这个问题?

How do I fix this problem?

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

推荐答案

这个溢出并不奇怪,因为算法在迭代时增加堆栈但退出条件是不可预测的,动作没有严格本地化(它们有敲对附近圆圈的影响),因此处理时间会很混乱.

It doesn't surprise this overflows because the algorithm grows the stack as it iterates but the exit condition is unpredictable, actions are not tightly localized (they have knock-on effects to nearby circles), so processing time will be chaotic.

我会重新考虑算法.考虑找到两个最近的圆,如果它们比给定的阈值相距更远,则中止.否则将它们分开一点并重复.

I would reconsider the algorithm. Consider finding the two closest circles, if these are further apart than a given threshold apart, abort. Otherwise move them apart a little and repeat.

这篇关于JavaScript 递归:超出最大调用堆栈大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆