【问题标题】:Don't execute a function until an inner animation completes在内部动画完成之前不要执行函数
【发布时间】:2011-01-21 03:01:01
【问题描述】:

简洁版

假设我有一个使用 jQuery 动画的函数。在动画完成之前,我不希望再次调用此函数。

例如,当调用下面的函数时,我不希望在内部计时器例程完成之前再次调用它:

function doSomething() {
   ... blah blah blah ...

   someElement.fadeOut(999, function() {
       // Don't let doSomething get invoked until the fadeOut animation has finished
   });
}

冗长的问题

我正在开发一个新闻自动收录器小部件,它在封面之下是一个无序列表。一次只显示列表元素的一个子集。每隔五秒,列表中的第一项会淡出,然后从列表顶部移除并添加到列表底部。

循环头条新闻的函数如下所示:

function advanceTicker(id) {
    // Get the first item
    var firstItem = $(id + ' li:first');
    var firstItemMarkup = firstItem.html();

    // Fade out the first item then move it to the bottom
    firstItem.fadeOut(999, function() {
        $(this).remove();  // Remove the first item

        // Tack the first item to the end of the list
        $(id).append('<li style="display:none">' + firstItemMarkup + '</li>');

        // Make the new first item visible
        $(id + ' li:first').show();
    });
}

当新闻项目每五秒循环一次时,上述函数运行良好,但如果我想在用户单击页面上的按钮(前进到下一个项目)时调用此函数,如果用户多次单击该按钮。即,新闻代码中有重复项。

我明白为什么(或者至少我认为我明白) - 在第一次单击按钮时执行的 fadeOut 调用在再次单击按钮时尚未完成,因此选择了相同的 firstItem在第二个按钮上单击并再次附加。

我的假设是我需要确保在“进行中”时不会调用此 advanceTicker 函数。有没有一种优雅的方式来做到这一点?我现在拥有的 - 感觉有点像黑客 - 是一个标志变量,如下所示:

var inAnimation = false;
function advanceTicker(id) {
    if (!inAnimation) {
        inAnimation = true;

        ...

        firstItem.fadeOut(999, function() {
             ...

             inAnimation = false;
        });
    }
}

上面的方法感觉不对,闻起来像一个竞争条件问题。

【问题讨论】:

  • 不要在 JavaScript 中阻塞 - 它会冻结 UI。
  • @Brian:我认为“阻止”在这里用错了——我相应地更新了问题标题。
  • 啊,在那种情况下,@ChaosPandion 的回答对我来说似乎是合理的。
  • @Scott...你想做这样的事情吗? jsfiddle.net/KeesCBakker/yQagG

标签: javascript jquery concurrency


【解决方案1】:

我知道的所有实现都存在于单线程上下文中,或者只允许单独的线程存在于沙箱中,所以我真的认为您的实现没有问题。

【讨论】:

  • 是的。这是正确的做法。网页是单线程的,事件处理程序总是运行到完成。
猜你喜欢
  • 1970-01-01
  • 2019-02-22
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多