Почему мой обратный вызов jQuery animation complete приводит к превышению максимального размера стека?

#javascript #jquery #jquery-animate #callstack

#javascript #jquery #jquery-animate #callstack

Вопрос:

это мой код, вызывающий мою функцию animateRotate. Внутренне это в основном просто вызывает $.animate . Но посмотрите сами:

 (function () {
    function rotate() {
        $motorblades.animateRotate(0, 360, 3000, { x: 117, y: 117 }, "linear", function () {
            if ($obj.attr("animate") == "true") {
                rotate();
            }
        });
    };

    rotate();
})();
  

Вот моя функция animateRotate:

 $.fn.animateRotate = function (startAngle, endAngle, duration, origin, easing, complete) {
    return this.each(function () {
        var elem = $(this),
            orig = typeof origin !== "undefined" ? origin : {x:0, y:0};

        $({ deg: startAngle }).animate({ deg: endAngle }, {
            duration: duration,
            easing: easing,
            step: function (now) {
                elem.attr("transform", "rotate("   now   " "   orig.x   " "   orig.y   ")");
            },
            complete: complete || $.noop
        });
    });
};
  

Сначала я думал, что это довольно очевидно, что происходит. Я вызываю rotate снова, как только анимация заканчивается, чтобы начать анимацию снова.
Но при дальнейшем исследовании я обнаружил, что это rotate завершается немедленно, поскольку animateRotate выполняет свою работу асинхронно.
Итак, я не уверен, почему стек должен увеличиваться.

Я уже нашел решение, но я не уверен, почему оно работает, и хотел бы знать, почему это так. Это решение пришло мне в голову, когда я подумал, что проблема в том, что функция rotate не завершается. Но функция завершается просто отлично.

Как только я завершаю rotate вызов функцией полного обратного вызова в setTimeout, он работает просто отлично.

Итак, теперь я здесь. С решением, которое работает, но я не доволен, поскольку я его не понимаю.

Кто-нибудь может сказать мне, что происходит?

Редактировать: Просто соберите все вместе в скрипте. К сожалению, это работает там: jsfiddle.net/hq07gucy

Еще одна вещь, которую я заметил: кажется, у меня сразу происходит сбой при переключении вкладок. Итак, если я оставлю вкладку, выполняющую анимацию, она сразу превысит максимальный размер стека, когда я вернусь. Есть идеи по этому поводу? Вот подробное сообщение:https://pastebin.com/BqGVtpc4

Это то, что показывает профилировщик производительности Chrome, когда я снова фокусирую вкладку: Профилировщик производительности Chrome

Это продолжается до конца. Но я не совсем понимаю, что происходит.

Комментарии:

1. Я не уверен, откуда $obj взялось это в вашем коде, но предполагая, что множественное число, которое $motorblades представляет более одного элемента и которое complete вызывается для каждого отдельного элемента в этом выборе, первый, который заканчивает свою анимацию, может перезапустить анимацию всех из них, включая те, которые не завершились. Не уверен, почему тайм-аут решает эту проблему, хотя вы могли бы добавить журналы, чтобы проверить это

2. Не могли бы вы создать минимальный, полный и проверяемый пример? чтобы показать, что такое $motorblades и $obj .

3. Хорошая идея. К сожалению, $motorblades это один объект (SVG-графика). Он назван только во множественном числе, поскольку на графике показано несколько блейдов.

4. Я попытаюсь настроить это в JS-скрипте. Дайте мне минуту.

5. Ага. Я собрал все вместе в скрипте, и это работает. Это прискорбно. jsfiddle.net/hq07gucy Обычно сообщение об ошибке появляется примерно через минуту.