在再次执行相同的函数之前,如何确保函数完成jQuery?

时间:2010-08-17 05:31:10

标签: jquery queue

所以,我有一个在.click()事件上执行的函数。我想知道如何确保在第一次运行完成之前该功能不会再次运行?因此,如果用户单击3次,该函数将运行3次,但run1将在run2启动之前完成。

我在想像.queue(),但我不确定如何实现它。

$(document).ready(function(){

    var numTabs = 10;
    var lastTab = numTabs;
    var currentClass;
    var newClass;

    // Portfolio Gallery

    $('.leftArrow').click(function () {
        $(this).queue(function () {
            // Moves Main 1-5 across
            for (i=1;i<=4;i++) {
                $('#main'+i).animate({'left': '+=229px'}, 'slow');
                $('#main'+i).removeAttr('style');
            }
            $('#main5').removeAttr('style');

            // Removes the Main Classes
            for (i=1;i<=5;i++) {
                $('#main'+i).removeClass('main'+i);
            }

            // Removes the active class from Main3
            $('#main3').removeClass('active');

            // Sets the New Main 1-5 IDs
            for (i=1;i<=5;i++) {
                currentClass = $('#main'+i).attr('class');
                currentClass = currentClass.substr(2);
                newClass = currentClass - 1;
                if (newClass == 0) {
                    newClass = lastTab;
                }
                $('.ex'+newClass).attr('id', 'main'+i);
            }

            // Sends Old Main 5 to the Stack
            if (newClass == lastTab) {
                newClass = 0;
            }
            $('.ex'+(newClass + 1)).removeAttr('id').addClass('theStack');

            // Reassigns the Main CLASSes
            for (i=1;i<=5;i++) {
                $('#main'+i).addClass('main'+i);
            }

            // Moves New Main 1 from Stack to Main 1 position
            $('#main1').removeClass('theStack');

            //Sets Main 3 as the new focus
            $('#main3').addClass('active');

            $(this).dequeue();
        });
    });
});


<div class="pMainHide">
    <div class="pMainShow">
        <div class="ex1 active main3" id="main3"><a href="images/image1.jpg">Image1</a></div>
        <div class="ex2 main4" id="main4"><a href="images/image2.jpg">Image2</a></div>
        <div class="ex3 main5" id="main5"><a href="images/image3.jpg">Image3</a></div>
        <div class="ex4 theStack"><a href="images/image4.jpg">Image4</a></div>
        <div class="ex5 theStack"><a href="images/image5.jpg">Image5</a></div>
        <div class="ex6 theStack"><a href="images/image6.jpg">Image6</a></div>
        <div class="ex7 theStack"><a href="images/image7.jpg">Image7</a></div>
        <div class="ex8 theStack"><a href="images/image8.jpg">Image8</a></div>
        <div class="ex9 main1" id="main1"><a href="images/image9.jpg">Image9</a></div>
        <div class="ex10 main2" id="main2"><a href="images/image10.jpg">Image10</a></div>
    </div>
</div>

很抱歉,如果这个帖子太大,之前没有使用Stack Overflow,这是我第一次真正尝试使用jQuery。

如果需要,可以添加CSS ...

3 个答案:

答案 0 :(得分:2)

问题是动画的每次迭代都在新元素上。然后更改元素ID,并将动画放入新元素的队列中。因此,您会遇到新元素在上一个动画完成之前在其队列中启动动画的情况。 JavaScript / jQuery 不会在动画期间暂停脚本的执行。

为此,jQuery在.animate()方法中提供了回调参数。 动画完成后,执行回调。我试图利用这个来强制执行所需的方式。

解决方案:

这仍然使用我在下面提供的解决方案,只是以稍微不同的方式实现。

$(document).ready(function(){
var numTabs = 10;        
var lastTab = numTabs;        
var currentClass;        
var newClass;        
var count = 0; // counter for myCallback
var executing = false;
var myQueue = 0;    
// Portfolio Gallery        

$('.leftArrow').click(doAnimate); // call a named function

function doAnimate(){
    if(!executing){
        executing = true;         
        // Moves Main 1-5 across  <- you are only moving 1-4 here      
        for (i=1;i<=4;i++) {                    // Add Callback--v    
            $('#main'+i).animate({'left': '+=229px'}, 'slow', myCallback);       
            $('#main'+i).removeAttr('style');        
        }        
        $('#main5').removeAttr('style');        

        // Removes the Main Classes        
        for (i=1;i<=5;i++) {        
            $('#main'+i).removeClass('main'+i);        
        }        

        // Removes the active class from Main3        
        $('#main3').removeClass('active');        

        // Sets the New Main 1-5 IDs        
        for (i=1;i<=5;i++) {        
            currentClass = $('#main'+i).attr('class');        
            currentClass = currentClass.substr(2);        
            newClass = currentClass - 1;        
            if (newClass == 0) {        
                newClass = lastTab;        
            }        
            $('.ex'+newClass).attr('id', 'main'+i);        
        }        

        // Sends Old Main 5 to the Stack        
        if (newClass == lastTab) {        
            newClass = 0;        
        }        
        $('.ex'+(newClass + 1)).removeAttr('id').addClass('theStack');        

        // Reassigns the Main CLASSes        
        for (i=1;i<=5;i++) {        
            $('#main'+i).addClass('main'+i);        
        }        

        // Moves New Main 1 from Stack to Main 1 position        
        $('#main1').removeClass('theStack');        

        //Sets Main 3 as the new focus        
        $('#main3').addClass('active');        

    } else {
        myQueue++;
    }   
}
function myCallback(){
    count++;
    if(count == 4){ // needs to be the same as your animate for loop
        count = 0;
        executing = false;
        if(myQueue == 0) return;
        myQueue--;
        doAnimate();
    }
}
});           

我选择了一个命名函数,以便更容易回复doAnimate()函数。

上面的帖子:


递归和一些布尔逻辑将完全满足您的要求。

试试这个:

var queue = 0;
var executing = false; 

$('.leftArrow').click(function () { 
    if (!executing) { 
        executing = true; 
        // Animation 
        executing = false;
        if(queue == 0) return;
        queue--;
        arguments.callee();
    } else { 
        queue++;
    } 
}); 
  • 动画运行的任何时候,queue都会递增1。
  • 任何时候queue不是0,递减queue,那么
  • arguments.callee()会调用您的匿名函数(这是递归)。就像使用$(this)一样,用于调用函数。

答案 1 :(得分:1)

也许这可以帮到你...

var executing = false;
$('.leftArrow').click(function () {
    if (!executing) {
      executing = true;
      // Execute animation and what not here.
      executing = false;
    } else {
      // just wait?
    }
});

答案 2 :(得分:1)

它在你身上。您应该创建一些boolean逻辑,或者禁用/启用按钮。

var block = false;
$('.leftArrow').click(function(){
    if(!block){
        block = true;
        // do lots of stuff
        block = false;            
    }
});

使用动画方法中的callback(在jQuery中)可能更好。像

$('.leftArrow').click(function(){
    var $this = $(this);

    $this.attr('disabled', 'disabled');
    $('somelement').fadeOut('slow', function(){
       $this.removeAttr('disabled');    
    });
});