我正在尝试遍历数组,然后在每次迭代中执行2个步骤(我们将其称为步骤1和步骤2)。在每次迭代之间以及在步骤1和步骤2之间应该有一个延迟。为增加延迟,我使用了setTimeout()方法。
基本上,类似-
对于我,从0到array.length
执行步骤1
等待2-5秒
执行步骤2并增加i
等待5到9秒钟,然后继续循环
下面是我的代码(来自相关问题-How to run setTimeout() with a random interval in each iteration in javascript?)-
function displayValue(){
var l = ['a' , 'b', 'c'];
var delay = 17000;
var i = 0;
function timerFunction(i){
if(i === l.length)
return;
setTimeout(()=>{
console.log("Step 1 - Iteration - " + i + " - " + l[i] + " - " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds());
setTimeout(() => {
console.log("Step 2 - Iteration - " + i + " - " + l[i] + " - " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds());
//i++ should probably be here but then i is never incremented
}, 2000 + Math.floor(Math.random() * 3000));
i++;
timerFunction(i);
}, delay);
delay = 5000 + Math.floor(Math.random() * 3500);
}
timerFunction(i);
}
displayValue();
当我运行上面的命令时,对于所有迭代,第2步都在第1步之前打印,并且循环经过array.length。输出类似于-
第1步-迭代-0-a-9:17:14
第2步-迭代-1-b-9:17:18
第1步-迭代-1-b-9:17:21
第2步-迭代-2-c-9:17:24
第1步-迭代-2-c-9:17:28
第2步-迭代-3-未定义-9:17:30
我怀疑这是因为,我需要在内部setTimeout()中增加i,但是当我将i++;
移动到那里时,它完全停止增加,可能是因为它在该方法中成为了局部变量。有没有一种方法可以通过内部setTimeout()中的引用传递i?还是其他解决方案,以防万一我完全离开?
答案 0 :(得分:1)
您的问题是您正在从第一个setTimeout回调继续循环,而此时,第二个仍未触发。
因此,您所需要做的就是从第二级超时内对timerFunction
进行递归调用
function displayValue() {
var l = ['a', 'b', 'c'];
var delay = 1000;
timerFunction(0);
function timerFunction(i) {
if (i === l.length)
return;
setTimeout(() => { // level 1
console.log("Step 1 - Iteration - " + i + " - " + l[i] + " - " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds());
// we start level2 timeout
setTimeout(() => {
console.log("Step 2 - Iteration - " + i + " - " + l[i] + " - " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds());
// only when this one is done, we start again
timerFunction(++i);
}, 500 + Math.floor(Math.random() * 500));
}, delay);
delay = 1000 + Math.floor(Math.random() * 800);
}
}
displayValue();
但是请注意,这与您对应该发生的情况的描述不符。在这里:
function displayValue() {
var l = ['a', 'b', 'c'];
timerFunction(0);
function timerFunction(i) {
if (i === l.length) {
return;
}
// Do Step 1
level1();
function level1() {
console.log("Step 1 - Iteration - " + i + " - " + l[i] + " - " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds());
// Wait for 2-5seconds (here /10)
setTimeout(level2, 200 + Math.floor(Math.random() * 300));
}
function level2() {
// Do Step2
console.log("Step 2 - Iteration - " + i + " - " + l[i] + " - " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds());
// and increment i
i++;
// wait for 5-9 seconds and continue the loop
setTimeout(() => timerFunction(i), 500 + Math.round(Math.random() * 400));
}
}
}
displayValue();
如果可以使用 async / await 语法,则可以将其重写得更干净:
displayValue();
function displayValue() {
const l = ['a', 'b', 'c'];
return iterate(0);
async function iterate(i) {
if(i >= l.length) return;
step(1, i);
await wait(200, 500);
step(2, i);
await wait(500, 900);
return iterate(++i);
}
function step(type, index) {
var d = new Date();
console.log("Step " + type +
" - Iteration - " + index +
" - " + l[index] +
" - " + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds()
);
}
}
function wait(min, max=min) {
const delay = min + Math.floor(Math.random() * (max - min));
return new Promise(res =>
setTimeout(res, delay)
);
}