我有一个 Array.each 函数,每次循环运行 25 次时,我需要暂停 5 秒。
Array.each(response.data, function(thing, index){
sendEmail(thing.id,sku,thing.email);
});
我尝试了各种方法,但它总是毫无延迟地调用 sendEMail 函数。有谁知道如何做到这一点?
循环可能会运行 15 到 500 次,具体取决于发送给它的数据。
谢谢。
Mootools 1.4.5
我有一个 Array.each 函数,每次循环运行 25 次时,我需要暂停 5 秒。
Array.each(response.data, function(thing, index){
sendEmail(thing.id,sku,thing.email);
});
我尝试了各种方法,但它总是毫无延迟地调用 sendEMail 函数。有谁知道如何做到这一点?
循环可能会运行 15 到 500 次,具体取决于发送给它的数据。
谢谢。
Mootools 1.4.5
Array.each
除非允许您从传入的回调中提前退出并允许您从任意索引恢复,否则您将无法在循环的中途停止循环迭代。您仍然需要将逻辑包裹在它周围来处理暂停。
另一种方法是自己动手。
var eachWithPause = function( iterable, iterations, timeout, fn, ctx ) {
// Sets up a callback to be passed back to the caller, allowing them
// to cancel the `setTimeout` call created within `loop`.
var timeoutID = 0;
var cancel = function() {
clearTimeout( timeoutID );
};
// `loop` will run the desired number of iterations, or iterate through
// the remainder of the `iterable`, whichever comes first. If there are
// still elements left after it is done, it will `setTimeout` for the
// desired amount of time.
var index = 0, l = iterable.length;
var loop = function() {
for ( var i = 0; i < iterations && index < l; ++i, ++index ) {
fn.call( ctx, iterable[ index ], index, iterable );
}
if ( index < l ) {
timeoutID = setTimeout( loop, timeout );
} else {
timeoutID = 0;
}
};
loop();
return cancel;
};
我在这里做的唯一有趣的事情是返回一个cancel
函数,该函数将为调用者提供一种调用它无法访问clearTimeout
的不断变化的方法。setTimeout
然后你会有类似的东西
var cancel = eachWithPause(response.data, 5, 5000, function(thing, index) {
sendEmail(thing.id, sku, thing.email);
});
如果您需要取消此操作,您可以简单地取消cancel()
它。
我会选择更通用的分块方法。
Array.implement({
chunkEach: function(offset, count, delay, fn, bind){
// get a chunk
var newOffset = offset + count,
chunk = this.slice(offset, newOffset),
ii = 0,
len = chunk.length;
if (!len)
return this;
// loop the chunk supporting natural index.
for (; ii< len; ++ii)
fn.call(bind, chunk[ii], offset + ii);
// move pointer and self call
if (newOffset < this.length)
this.chunkEach.delay(delay, this, [newOffset, count, delay, fn, bind]);
// pointless chaining return as its async.
return this;
}
});
使用,例如,以 15 个块为单位循环电子邮件地址数组,并暂停 2 秒,将功能范围保持在具有选项属性的虚构对象中:
list.chunkEach(0, 15, 2000, function(el, index){
console.log(this.options);
new Element('div[html='+index + '. ' + el +']').inject(o);
}, this);
见http://jsfiddle.net/dimitar/aYwab/
它的粗糙 - 缺乏对参数和东西的检查,但它会做你想做的事。
在这里解决延迟的责任可能存在疑问。您正在发送电子邮件,大概是通过 ajax。模棱两可的延迟是不可扩展的。
您应该考虑使sendEmail
函数可链接 - 只需将数组和索引传递给它,如果索引小于数组长度 - 1,sendEmail
则从onSuccess
下一个索引再次调用。如果上次发送失败,这也允许您中断或重试。
此外,您可以使用 Promises。
I would split your ploblem in two different subproblem, you want a way to group an Array by X items:
Array.implement('paginate', function(count){
var result = [], pageIndex = -1
for(var i=0, max = this.length; i<max; i++){
if (i%count==0){
pageIndex++
result.push([])
}
result[pageIndex].push(this[i])
}
return result;
});
then you want to process each 'page' of the Array and wait Y seconds before doing anything with the rest of the data.
function process(data, index, delay){
workondata(data[index]);
if( data.length-index >1 ) setTimeout(
function(){
process(data, index +1, delay)
},
delay
);
}
So I believe something like this: http://jsfiddle.net/kentaromiura/SmyU8/ would do the job.