1

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.

t-jam
  • 811
  • 1
  • 6
  • 21
  • So, the only question is *How to update triggered variable inside the queue, check it and fire an event?*. – gurvinder372 Nov 15 '17 at 06:42
  • Yeah, and fire that event only once after the queue completes. – t-jam Nov 15 '17 at 06:43
  • Can you create a working snippet using `<>` so that it is easier to debug? – gurvinder372 Nov 15 '17 at 06:55
  • Added fiddle link in question. – t-jam Nov 15 '17 at 07:14
  • you can share that what you intended to do with your example, it's clear about variable concept however it's more better to share your real intention. – mlimon Nov 15 '17 at 07:21
  • @mlbd The actual purpose is a bit complex so I opted not to confuse the question / example with unnecessary detail. In short, there's a matching process happening inside the queue where (depending on data attributes) some items will have a class applied if matched to a selection elsewhere. If a match is found while processing in the queue, the 'triggered' variable will be updated. After the queue, depending on the value of the variable, an event will be fired on the body. I only want one event fired though, and it needs to check the variable value after the queue completes. – t-jam Nov 15 '17 at 07:26
  • Check this updated fiddle https://jsfiddle.net/0wwm1oqt/2/ – gurvinder372 Nov 15 '17 at 09:15

1 Answers1

1

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>
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • Thanks, though I now realise it may not be explicit in the question that *checking* is important because I want to fire a different event if false after the queue - it's not just true that's important... – t-jam Nov 15 '17 at 09:50
  • 1
    Ohh, in that case, keep another variable to check if the `queue` functions has been completed or not. – gurvinder372 Nov 15 '17 at 09:51
  • Found a good way of doing this: by comparing `$(this).index()` to the object length in the queue, we can identify if it's the loop is on its last cycle, then fire the trigger check. – t-jam Nov 15 '17 at 10:21
  • @t-jam you mean inside the `queue` itself? Yes, that should work as well. – gurvinder372 Nov 15 '17 at 10:22