setTimeout不会在循环中暂停迭代

时间:2015-09-14 14:51:20

标签: javascript jquery loops

我正在尝试遍历订单列表,暂停每个订单3秒钟。然后一旦完成,再循环一次。

在下面的代码段中,如果循环启用,它似乎在第一个循环完成之前再次启动循环。

每次调用display_notification之间的3秒暂停也不起作用。

start: function() { 
    $.each(this.orders, function(index, order) {
        setTimeout(function() {
            console.log ('show notification');
            recentlyApp.display_notification(order);
        }, index * 3000);
    });
    if (this.settings.loop) {
        this.start();
    }
},
display_notification: function(order) {
    console.log(order);
}

2 个答案:

答案 0 :(得分:1)

一旦完成设置超时功能的循环,您就会调用this.start()

跟踪index的最后一个值并使用它来设置start()调用的超时时间,或者将调用设置为start()在您设置的最后一个超时功能中循环。

答案 1 :(得分:1)

As soon as you're already using jQuery, you can create a plugin to loop through an array in an interval.

Example:

// timer function that loops through an array with in a given interval
$.timer = function (list, callback, time/*, onFinish, index*/) {
  var onFinish = arguments.length > 3 ? arguments[3] : void 0,
      index = arguments.length > 4 ? arguments[4] : 0;
  
  if (index < list.length) {
    list.__timed = setTimeout(function() {
      callback.call(this, index, list[index]);
      $.timer(list, callback, time, onFinish, ++index);
    }, time);
  }
  else if (onFinish){
    onFinish.call(this);
  }

  return {
    cancel: function() {
      if (list.__timed !== void 0) {
        clearTimeout(list.__timed);
        delete list.__timed;
      }
    }
  };
}

// usage
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var timer = $.timer(arr, function (index, item) {
  document.querySelector('div').insertAdjacentHTML('beforeend', '<div>' + item + '</div>');
}, 3000, function() {
  document.querySelector('div').insertAdjacentHTML('beforeend', '<div>Finished</div>');
});

// cancelling the loop
$('button').click(function(e) {
  timer.cancel();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>Cancel timer</button>

So, in your scenario, it would be something like this:

start: function() { 
  $.timer(this.orders, function(index, order) {
    console.log('show notification');
    recentlyApp.display_notification(order);
  }, 3000, this.settings.loop ? this.start : void 0);
},
display_notification: function(order) {
  console.log(order);
}

UPDATE

Now, the $.timer is returning an object with the cancel method, so you can cancel the loop at anytime by calling .cancel();.

I've created a __timed property into the array to always get the last setTimeout executed, so when you call the cancel method, it calls the clearTimeout for what it was going to call next.