如何在 x 次迭代后暂停循环 x 秒,然后继续



所以我有一个数组,其中包含我想加入的频道名称列表(这是针对 Twitch 聊天机器人的(,用于加入频道的 API 端点的速率限制为每 50 秒 15 次加入。我正在尝试找出遍历 50 个通道名称的最佳方法,暂停 15 秒,然后继续遍历数组的其余部分,每 50 个名称暂停 15 秒。

我最初尝试使用伪造的 100 值数组、模运算符和 setTimeout 进行通用 for 循环,但无济于事。但老实说,我不知道从哪里开始,所以这很糟糕。

let array = ([...Array(100).keys()].map(x => ++x))
for (var i = 1; i < array.length; i++) {
    if (i % 50 === 0) {
        setTimeout(() => {
            console.log('Waiting 15 seconds.')
        }, 15000);
    } else {
        console.log(array[i])
    }
}

理想情况下,它会记录 1-50,然后等待 15 秒,然后记录 51-100。

您可以使用asyncawait以相当简单的方式暂停for循环:

// utility function that returns a promise that resolves after t milliseconds
function delay(t) {
    return new Promise(resolve => {
        setTimeout(resolve, t);
    });
}
async function processArray(array) {
    for (let i = 1; i < array.length; i++) {
        if (i % 50 === 0) {
            await delay(15 * 1000);
        } 
        console.log(array[i])
    }
}
let data = ([...Array(100).keys()].map(x => ++x))
processArray(data).then(() => {
    console.log("all done");
});

仅供参考,我不太明白为什么您尝试在 100 元素数组上使用索引 1 到 100。 我认为您应该将索引 0 到 99 用于 100 元素数组。 我把代码留给你的假设是,也许你是故意这样做的。

const _ = require('lodash');

使用迭代器/生成器,以便您可以控制何时需要下一个项目,而不是努力"停止"循环的执行。

function* myIterator(data) {
  for (const item of data)
    yield item;
}

然后设置一个将执行实际执行的函数,将迭代器作为参数。这样,每次调用它时,您都可以传入迭代器,以便它记住它停止的位置。

function execute(it) {
  // We want to do this in batches of 50
  // (but test with lower value to better see how it works)
  _.range(0, 50).forEach(() => {
    // Get next item
    const item = it.next();
    // If no more items, we're done
    if (item.done) return;
    else {
      // Do something with the item
      console.log(item.value);
    };
  });
  // Pause for 15 seconds and then continue execution
  setTimeout(() => execute(it), 15000);
}

创建数据,从中生成迭代器,然后执行。

(function main() {
  const data = _.range(1, 101);
  const it = myIterator(data);
  execute(it);
})();

试试这个

 let array = ([...Array(100).keys()].map(x => ++x))
const startLoop = currentIndex => {
  for (let i = currentIndex; i < array.length; i++) {
    if (i % 50 === 0) {
        setTimeout(() => {
           console.log('Waiting 15 seconds.');
           startLoop(i + 1);
        }, 15000)
        break;
    } 
     console.log(array[i])
  }
}
startLoop(1);

从头开始编写递归循环函数(以牺牲性能为代价(可能是最简单的解决方案,但您可以使用 while 循环和 Promise 迭代方式完成此操作,而不会影响性能。

在下面的代码中,每次循环的从 1 开始的索引达到 batch_size 的倍数时,都会调用一个 await,该停止执行,直到 Promise 解析。承诺只是一个setTimeout调用,它等待pause_ms,然后允许循环继续。这里的值略有不同,只是为了使测试更容易;您可以自由更改它们以满足您的需求。

const vals = [...new Array(20)].map(() => Math.floor(Math.random() * 9) + 1);
console.log(vals);
async function iterateBatches(arr, batch_size, pause_ms) {
  // Create a promise generator that will automatically resolve after the desired number of millseconds.
  const wait = () => new Promise(r => {
    setTimeout(r, pause_ms)
  });
  
  // Establish the starting and ending points for the iteration.
  const len = arr.length;
  let i = 0;
  // As long as the loop hasn't reached the final element,
  while (i < len) {
    // Perform an operation with the value in your array.
    console.log(i, vals[i]);
    // If we've reached the end of the array, break out of the loop to prevent an unneeded iteration.
    if (i >= len - 1) break;
    // Increment the index (this is also equal to the 1-based index, which saves us some lines).
    // If the 1-based index is a multiple of batch_size and we're not on the first iteration, wait for our promise generator.
    if (++i % batch_size === 0 && i > 0) await wait();
  }
  console.log("Done!");
}
iterateBatches(vals, 5, 2000);

您可以手动创建循环。下面是一个简化的示例...

var array = ['a','b','c','d','e','f'];
var i = 0;
function loop(){
   if(i>=array.length) return;
   if(i==3){
      setTimeout(function(){
          i++;
          loop();          
      },15000);
      return;  
   }
   i++;
   console.log(array[i]);
   loop();
}
loop();

最新更新