Search code examples
javascriptjquerycsscallbackjquery-callback

`queue` callback only executes once?


I have a jQuery function that loops. What I want to do is for the $bird_wing_left element to rotate 30 degrees and then rotate back to 0 degree (in an infinite loop).

$(document).ready(function() {

    var rotate = 0;

    setInterval(function(){ 

        rotate = 30;

        $bird_wing_left.css({ transform: "rotate(" + rotate + "deg)" }).delay(1000).queue(function(){
            rotate = 0;
            $(this).css({ transform: "rotate(" + rotate + "deg)" });
        });

    }, 3000);
});

The first time it did rotate 30 degrees, then to 0 degrees, then to 30 degrees. However, afterwards, it seems to ignore the callback (which resets the degree value to 0), hence, it just keeps on being at 30 degrees on and on.

What could be the issue?

This is the jsFiddle: https://jsfiddle.net/iamacatperson/86z26hdw/


Solution

  • When you queue a function, within the function you have to dequeue (or call "next", more below) to allow the queue to continue processing (as shown in the examples). Just add $(this).dequeue() within your queue callback:

    var $bird_wing_left = $("#wing");
    $(document).ready(function() {
    
      var rotate = 0;
    
      setInterval(function() {
    
        rotate = rotate + 30;
    
        $bird_wing_left.css({
          transform: "rotate(" + rotate + "deg)"
        }).delay(1000).queue(function() {
          rotate = rotate - 30;
          $(this).css({
            transform: "rotate(" + rotate + "deg)"
          }).dequeue();       // <====================
        });
    
      }, 3000);
    });
    body {
      padding-top: 2em;
    }
    <div id="wing" style="width: 10em">Bird wing</div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

    Alternately, since jQuery 1.4 the queue callback has been given an argument (traditionally called next) it can call to keep the queue going:

    var $bird_wing_left = $("#wing");
    $(document).ready(function() {
    
      var rotate = 0;
    
      setInterval(function() {
    
        rotate = rotate + 30;
    
        $bird_wing_left.css({
          transform: "rotate(" + rotate + "deg)"
        }).delay(1000).queue(function(next) {  // <=====
          rotate = rotate - 30;
          $(this).css({
            transform: "rotate(" + rotate + "deg)"
          });
        
          next();                              // <=====
        });
    
      }, 3000);
    });
    body {
      padding-top: 2em;
    }
    <div id="wing" style="width: 10em">Bird wing</div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>


    Side note: You can use += and -= if you like, e.g. rotate += 30; and rotate -= 30;