超出最大调用堆栈大小 - 知道原因(功能太多)但如何修复它?

时间:2014-03-24 09:47:52

标签: javascript jquery stack-overflow chaining

在我的页面上,我有一段基于嵌套函数的简单代码,这有助于我以正确的顺序逐个显示一个元素:

        var fade = 700;
        $('#s2icon-center').fadeIn(fade, function() {
            $('#s2icon-1').fadeIn(fade, function() {
                $('#s2icon-3, #s2icon-9').fadeIn(fade, function() {
                    $('#s2icon-6, #s2icon-11, #s2icon-17').fadeIn(fade, function() {
                        $('#s2icon-5, #s2icon-14, #s2icon-19').fadeIn(fade, function() {
                            $('#s2icon-8, #s2icon-13, #s2icon-22').fadeIn(fade, function() {
                                $('#s2icon-2, #s2icon-16, #s2icon-21').fadeIn(fade, function() {
                                    $('#s2icon-4, #s2icon-10, #s2icon-24').fadeIn(fade, function() {
                                        $('#s2icon-7, #s2icon-12, #s2icon-18').fadeIn(fade, function() {
                                            $('#s2icon-15, #s2icon-20').fadeIn(fade, function() {
                                                $('#s2icon-23').fadeIn(fade);
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });

但是在我看来,由于在一个地方使用了太多的功能,页面变得迟钝,我在控制台中出现错误:'未捕获RangeError:超出最大调用堆栈大小'

现在我向你们提出的问题是,如何(以最简单的方式)我可以获得相同的效果但效率更高?

提前致谢!

-------------编辑

这里看起来应该如何: Codepen Full view

代码就在这里: Codepen DEMO

2 个答案:

答案 0 :(得分:2)

您似乎遇到的问题是animation回调:

  

Complete Function

     

如果提供,则完成回调函数   动画完成。这对于串联不同可能很有用   动画按顺序组合在一起。回调不会发送任何   参数,但这被设置为动画的DOM元素。如果   多个元素是动画的,每次执行一次回调   匹配元素,而不是整个动画的一次。

那不是你想要的。相反,使用promise,这也应该防止堆栈溢出。

var fade = 700;
$('#s2icon-center').fadeIn(fade).promise().then(function() {
    return $('#s2icon-1').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-3, #s2icon-9').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-6, #s2icon-11, #s2icon-17').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-5, #s2icon-14, #s2icon-19').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-8, #s2icon-13, #s2icon-22').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-2, #s2icon-16, #s2icon-21').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-4, #s2icon-10, #s2icon-24').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-7, #s2icon-12, #s2icon-18').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-15, #s2icon-20').fadeIn(fade).promise();
}).then(function() {   
    return $('#s2icon-23').fadeIn(fade).promise();
}).then(function() {   
    console.log("all finished");
});

答案 1 :(得分:1)

您可以使用delay()将链中下一个函数的执行延迟指定的时间。

var fade = 700;

// ID's of all elements you want to fade
var elems = ["#d1", "#d2", "#d3", "#d4", "#d5"];
// In your case:
// var elems = ['#s2icon-center', '#s2icon-1', '#s2icon-3, #s2icon-9', '#s2icon-6, #s2icon-11, #s2icon-17']; // and so on...

// Loop over all those elements
for (var e = 0; e < elems.length; e += 1) {
    // Get element by it's ID (from the array)
    var element = $(elems[e]);

    // Use .delay() to delay execution of fade by the amount
    // "fade * e", so 0, 700, 1400, ...
    element.delay(fade * e).fadeOut(fade);    
}

(请注意,我已使用fadeOut()保持示例清晰 - 您需要将其更改为fadeOut()

DEMO