1

Please help! I am making an alert system that fires multiple alerts at the same time but I actually want them to appear one at a time so that it looks like a command promt in bash it is the sleep function.

Take a look https://jsfiddle.net/14cmgrLj/10/

  function iterateThru (message, status) {
    var time = 500;
    $.each(alertsArray, function(index, item) {
      
       //setTimeout(function(){ fireAlerts(message, status); }, 1000);
        setTimeout(fireAlerts, 100, message, status);
    
        //remove
    setTimeout(removeAlert, 4000);
    });  
    // empty array
    alertsArray = [];
  }

I am calling this function from all over my site. In an effort to make them fire 1-by-1 - everytime my the function is used the object is added to an array and then I use .each to loop through each of them with a setTimeout but they still fire all at once. How can i loop through the array's items with a delay between each.

Thanks in Advance

Omar
  • 2,726
  • 2
  • 32
  • 65
  • Do your fireAlert and removeAlert functions work as expected> – ayushgp Apr 22 '16 at 17:24
  • The setTimeouts cause your code to run asynchronously which is what is causing the problem. You need to use a recursive loop instead. – nurdyguy Apr 22 '16 at 17:36
  • FireAlert and removeAlert functions work but not the way i want. https://jsfiddle.net/14cmgrLj/10/ @ayushgp – Omar Apr 22 '16 at 18:34

4 Answers4

3

You could use jQuery's .delay function to manage the queue jQuery: Can I call delay() between addClass() and such?


Or...

Use an IIFE to manage the incremental wait for each message in the loop.

Fiddle: https://jsfiddle.net/14cmgrLj/11/

It needs a little more work because if you click the create alert button after the first set completes but before they are hidden the timing is all screwy.

function fireAlerts(alerts) {      
  $.each(alerts, function(index, value) {
    // Use IIFE to multiply Wait x Index
    (function(index, value) {
      var wait = index * 1000 + 1000;
      setTimeout(function() {
        // Show Alert
        // [...]
        }
      }, wait);
    })(index, value);
  });
}
Community
  • 1
  • 1
Justin
  • 26,443
  • 16
  • 111
  • 128
0

As noted before setTimeout just schedule tasks and returns immediately. So use something like this:

<script>
var alertArray=[];
function showAlert(){
    var al = alertArray.shift();// removes and return first element
    if(al !== undefined){
        alert(al);
    }
    setTimeout(showAlert, 4000);
}
setTimeout(showAlert, 4000);
function addAlert(al){
    alertArray.push(al);//add new alert to the end
}
</script>
Alex Kudryashev
  • 9,120
  • 3
  • 27
  • 36
0

Ok So I found the problem in your code. The setTimeout function calls the code written inside the function after the given time. But is Asynchronous, ie, it doesn't block. So when you were looping over each element, the functions were called, all three at about the same time(you gave same timeout to them). What you need to do is define a new variable(time b/w each line appearing) and increment it in every iteration.

function iterateThru (message, status) {
    var time = 0;
    $.each(alertsArray, function(index, item) {

        setTimeout(function(){ 
            fireAlerts(message, status); 
        }, time);
        time += 1000;

        //remove
        setTimeout(removeAlert, 4000);  //Change value of 4000 accordingly.
    });  
    // empty array
    alertsArray = [];
  }
ayushgp
  • 4,891
  • 8
  • 40
  • 75
0

The way you had written things was doing some odd stuff, so I went with this alteration of your solution:

  • Add alerts the screen using a 'wait' function created from jQuery Deferred
  • Add alerts to an array if you need them (un-comment that)
  • I moved your globals into a namespace called myApp.

Try it out here: https://jsfiddle.net/MarkSchultheiss/14cmgrLj/14/

Altered code:

//create app or use one if exists
var myApp = myApp || {};
// add alerts data
myApp.alerts = {
  count: 0,
  alertDelay: 3000,
  defaultStatus: "1",
  alertsArray: []
};
myApp.func = {
  wait: function(ms) {
    var defer = $.Deferred();
    setTimeout(function() {
      defer.resolve();
    }, ms);
    return defer;
  },
  addAlert: function(message, status) {
    status = status || myApp.alerts.defaultStatus;
    myApp.alerts.count++; // counts how many have ran
    var alert = [message, status, myApp.alerts.count];
    // uncomment if you need keep track of them:
    // myApp.alerts.alertsArray.push(alert);
    myApp.func.fireAlert(alert, myApp.alerts.alertDelay);
  },
  fireAlert: function(item, delay, index) {
    $("#terminal").append("<span class='d" + item[2] + "'>" + item[0] + "</span><br />");
    myApp.func.wait(delay).then(function() {
      $("#terminal").find('.d' + item[2]).addClass('fadeOutDown');
    })
  }
};
//====== Trigger ======//
$("#trigger").click(function(event) {
  console.log("There have been " + myApp.alerts.count + " alerts ran");
  console.log(myApp.alerts.alertsArray);
  myApp.func.addAlert($('#field').val(), 2);
  myApp.func.addAlert($('#field').val(), 2);
  myApp.func.addAlert($('#field').val(), 2);
});
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100