所以我有一个数组,其中包含我想加入的频道名称列表(这是针对 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。
async
和await
以相当简单的方式暂停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();