t-jam
t-jam

Reputation: 800

How to trigger an action once with a jQuery queue() loop

I have a jQuery object with a number of elements, e.g. $('.items'). I have these items going through some processing inside a queue(), and depending on conditions, I want to change a variable. After the queue has completed, I want to check that variable and trigger an event. My issue is that checking the variable and doing something inside the queue will fire multiple times (for each node in the jQuery object being looped through), and doing this outside the queue happens before the queue finishes, so it's not catching the variable update.

For example:

var triggered = false;

$('.items').addClass('doing-things').delay(500).queue(function(next) {
  // Do some things
  console.log('Things are happening');
  // Check conditions and change variable
  if ( someCondition ) {
    triggered = true;
  }
  // Finished doing things
  $(this).removeClass('doing-things');
  next();
}).queue(function(next) {
  // Check inside queue
  if ( triggered ) { 
    // This will be fired repeatedly in the loop, $('.items').length number of times
    console.log(triggered); 
  }
  next();
});

// Check after queue
if ( triggered ) { 
  // This will fire once, but will be false, because it will fire before the queue finishes (with delays)
  console.log(triggered); 
}

Can anyone point me towards how I can update the triggered variable inside the queue, then check it and fire an event (or in this example, do console.log(triggered)) only once?

Edit: Example fiddle here for debugging.

Upvotes: 1

Views: 251

Answers (1)

gurvinder372
gurvinder372

Reputation: 68393

Rather than simply checking for triggered to be true, you wait for triggered to be true

Demo

var triggered = false,
		$test1 = $('#test1'),
    $test2 = $('#test2');

$('.item').addClass('doing-things').delay(1000).queue(function(next) {
  // Do some things
  console.log('Things are happening');
  // Check a condition and change variable
  if ( !triggered ) {
    triggered = true;
  }
  // Finished doing things
  $(this).removeClass('doing-things');
  next();
}).queue(function(next) {
  // Check inside queue
  if ( triggered ) { 
    // This will be fired repeatedly in the loop, $('.items').length number of times
    $test1.append('<div>Fired</div>'); 
  }
  next();
});
triggerEvent();

function triggerEvent ()
{
   if( !triggered )
   {
     setTimeout( triggerEvent, 1000 );
   }
   else
   {
       $test2.append('<div>Fired</div>'); 
   }
}
.item {
  padding: 10px;
  margin: 10px;
  border: 2px solid #aaa;
}

.item.doing-things {
  border-color: #f00;
}

.test {
  padding: 20px;
  margin: 10px;
  background: #fff;
}

#test1 {
  border: 2px solid #0f0;
}

#test2 {
  border: 2px solid #00f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>

<div id="test1" class="test"></div>
<div id="test2" class="test"></div>

Upvotes: 1

Related Questions