具有多个setTimeouts的复杂递归函数调用(清除问题)

时间:2015-12-03 22:31:26

标签: javascript jquery recursion timer

我创建了一个在瓷砖之间设置动画的功能,我想在悬停时暂停。

以下是它如何工作的基本概述:有3个相邻的瓷砖循环通过它们自己的dinstinct瓷砖组,悬停时特定的瓷砖应该暂停,然后当它被淘汰时它应该恢复。

在代码中,有一个计时器,在该计时器中将一个类添加到图块中,该图块为其设置动画并将下一个图块附加到其上。然后,在此计时器内,创建另一个setTimeout,删除动画类,删除刚刚显示的图块并显示刚刚附加的图块。然后,有一个最终的setTimeout,它使用所有相同的传递参数再次递归调用该函数(因此它永远循环)。在函数内部,我有一些绑定的事件,用于监视鼠标悬停并在单个图块上鼠标移出。它们用于暂停计时器悬停并在鼠标移出时再次启动它。

该函数按预期工作,除了mouseout绑定由于某种原因递归调用函数被调用两次为2或3个不同的tile(其中1-2个不是我翻过来的tile)并导致奇怪的结果。任何人都知道这一部分:

.one("mouseout", function () {
        animateTiles(content, tile);
    });

在mouseout上用不同的参数调用倍数?

以下是代码的简化版本:

var l_tAnimateTilesTimer = null,
l_tAnimateTilesFlipTimer = null,
l_tAnimateTilesRecursiveTimer = null;
function animateTiles(content, tile) {
    l_tAnimateTilesTimer = setTimeout(function () {
        appendNextTileContent(content, tile);
        tile.addClass(l_sAnimationClass);
        l_tAnimateTilesFlipTimer = setTimeout(function () {
            tile.removeClass(l_sAnimationClass)
            .find(".front").remove();
            tile.find(".back").removeClass("back").addClass("front");
            l_tAnimateTilesRecursiveTimer = setTimeout(function () {
                animateTiles(content, tile);
            }, 5000);
        }, 300);
    }, 2000);
    tile.off().one("mouseover", function () {
        if (l_tAnimateTilesTimer !== null) {
            clearTimeout(l_tAnimateTilesTimer);
            l_tAnimateTilesTimer = null;
        }
        if (l_tAnimateTilesFlipTimer !== null) {
            clearTimeout(l_tAnimateTilesFlipTimer);
            l_tAnimateTilesFlipTimer = null;
        }
        if (l_tAnimateTilesRecursiveTimer !== null) {
            clearTimeout(l_tAnimateTilesRecursiveTimer);
            l_tAnimateTilesRecursiveTimer = null;
        }
    }).one("mouseout", function () {
        animateTiles(content, tile);
    });
};
var tile = $("#tile_wrap .right");
var content = {
   title = "tile 1",
   id = "tile_1_id"
};
animateTiles(tile, content); //an example of calling it

如果您需要我澄清任何事情,请告诉我。非常感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:2)

将在元素或其任何嵌套元素上触发Mouseover和mouseout。尝试使用mouseenter和mouseleave代替。

答案 1 :(得分:1)

如果有人好奇,我想出答案,我需要在函数内移动setTimeout变量创建(因此它们是特定函数调用的本地)。我还在l_tAnimateTilesTimer中添加了鼠标事件,但我不确定这是否必要。这是一个完整的例子:

function animateTiles(content, tile) {
var l_tAnimateTilesTimer = null,
l_tAnimateTilesFlipTimer = null,
l_tAnimateTilesRecursiveTimer = null;
l_tAnimateTilesTimer = setTimeout(function () {
    tile.off().one("mouseover", function () {
        if (l_tAnimateTilesTimer !== null) {
            clearTimeout(l_tAnimateTilesTimer);
            l_tAnimateTilesTimer = null;
        }
        if (l_tAnimateTilesFlipTimer !== null) {
            clearTimeout(l_tAnimateTilesFlipTimer);
            l_tAnimateTilesFlipTimer = null;
        }
        if (l_tAnimateTilesRecursiveTimer !== null) {
            clearTimeout(l_tAnimateTilesRecursiveTimer);
            l_tAnimateTilesRecursiveTimer = null;
        }
    }).one("mouseout", function () {
        animateTiles(content, tile);
    });
        appendNextTileContent(content, tile);
        tile.addClass(l_sAnimationClass);
        l_tAnimateTilesFlipTimer = setTimeout(function () {
            tile.removeClass(l_sAnimationClass)
            .find(".front").remove();
            tile.find(".back").removeClass("back").addClass("front");
            l_tAnimateTilesRecursiveTimer = setTimeout(function () {
                animateTiles(content, tile);
            }, 5000);
        }, 300);
    }, 2000);
    tile.off().one("mouseover", function () {
        if (l_tAnimateTilesTimer !== null) {
            clearTimeout(l_tAnimateTilesTimer);
            l_tAnimateTilesTimer = null;
        }
        if (l_tAnimateTilesFlipTimer !== null) {
            clearTimeout(l_tAnimateTilesFlipTimer);
            l_tAnimateTilesFlipTimer = null;
        }
        if (l_tAnimateTilesRecursiveTimer !== null) {
            clearTimeout(l_tAnimateTilesRecursiveTimer);
            l_tAnimateTilesRecursiveTimer = null;
        }
    }).one("mouseout", function () {
        animateTiles(content, tile);
    });
};
var tile = $("#tile_wrap .right");
var content = {
   title = "tile 1",
   id = "tile_1_id"
};
animateTiles(tile, content); //an example of calling it