jquery .each循环执行每个数组项,并在它们之间有延迟

时间:2021-01-03 14:28:22

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.

请帮忙!我正在建立一个同时触发多个警报的警报系统,但我实际上希望它们一次出现一个,这样它看起来像bash中的命令promt它是睡眠功能。

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

看看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.

我从我的网站上调用这个函数。为了让它们逐个点火 - 每次使用我的函数时,对象都被添加到一个数组中,然后我使用.each用setTimeout遍历它们,但是它们仍然会一次性触发。我如何循环遍历数组的项目,每个项目之间有延迟。

Thanks in Advance

提前致谢

4 个解决方案

#1


2  

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

您可以使用jQuery的.delay函数来管理队列jQuery:我可以在addClass()之间调用delay()吗?


Or...

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

使用IIFE管理循环中每条消息的增量等待。

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);
  });
}

#2


0  

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

如前所述,setTimeout只是安排任务并立即返回。所以使用这样的东西:

<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>

#3


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.

好的,我在你的代码中发现了问题。 setTimeout函数调用在给定时间之后写入函数内部的代码。但是是异步的,即它不会阻塞。因此,当您遍历每个元素时,函数被调用,这三个函数几乎同时被调用(您给它们提供了相同的超时)。您需要做的是定义一个新变量(每条线出现的时间b / w)并在每次迭代中递增它。

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 = [];
  }

#4


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
  • 使用从jQuery Deferred创建的“wait”函数在屏幕上添加警报

  • Add alerts to an array if you need them (un-comment that)
  • 如果需要,可以向阵列添加警报(取消注释)

  • I moved your globals into a namespace called myApp.
  • 我将你的全局变成了一个名为myApp的命名空间。

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

在这里尝试: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);
});

#1


2  

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

您可以使用jQuery的.delay函数来管理队列jQuery:我可以在addClass()之间调用delay()吗?


Or...

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

使用IIFE管理循环中每条消息的增量等待。

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);
  });
}

#2


0  

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

如前所述,setTimeout只是安排任务并立即返回。所以使用这样的东西:

<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>

#3


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.

好的,我在你的代码中发现了问题。 setTimeout函数调用在给定时间之后写入函数内部的代码。但是是异步的,即它不会阻塞。因此,当您遍历每个元素时,函数被调用,这三个函数几乎同时被调用(您给它们提供了相同的超时)。您需要做的是定义一个新变量(每条线出现的时间b / w)并在每次迭代中递增它。

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 = [];
  }

#4


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
  • 使用从jQuery Deferred创建的“wait”函数在屏幕上添加警报

  • Add alerts to an array if you need them (un-comment that)
  • 如果需要,可以向阵列添加警报(取消注释)

  • I moved your globals into a namespace called myApp.
  • 我将你的全局变成了一个名为myApp的命名空间。

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

在这里尝试: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);
});