1

ループが 25 回実行されるたびに 5 秒間一時停止する必要がある Array.each 関数があります。

Array.each(response.data, function(thing, index){
    sendEmail(thing.id,sku,thing.email);
});

さまざまな方法を試しましたが、常に遅延なく sendEMail 関数を呼び出すだけです。誰もこれを行う方法を知っていますか?

ループは、送信されるデータに応じて、15 ~ 500 回実行される場合があります。

ありがとう。

ムーツール 1.4.5

4

3 に答える 3

1

もっと一般的なチャンク方法を選びます。

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

たとえば、2秒間休止して15のチャンクで電子メールアドレスのループ配列を使用し、関数のスコープをオプションプロパティを持つ架空のオブジェクトに保持します。

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を使用することもできます。

于 2013-02-16T14:01:00.640 に答える
1

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ものを呼び出す方法を提供する関数を返すことです。clearTimeoutsetTimeout

次に、次のようなものがあります

var cancel = eachWithPause(response.data, 5, 5000, function(thing, index) {
  sendEmail(thing.id, sku, thing.email);
});

この操作をキャンセルする必要がある場合は、簡単にキャンセルできますcancel()

于 2013-02-15T05:11:14.383 に答える
0

私はあなたの問題を2つの異なるサブ問題に分割します.Xアイテムで配列をグループ化する方法が必要です:

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

次に、配列の各「ページ」を処理し、残りのデータを処理する前に Y 秒待機します。

function process(data, index, delay){
   workondata(data[index]);
   if( data.length-index >1 ) setTimeout(
        function(){
           process(data, index +1, delay)
        },
        delay
   );
}

だから私は次のようなものを信じています: http://jsfiddle.net/kentaromiura/SmyU8/ は仕事をするでしょう。

于 2013-02-16T16:40:37.150 に答える