我试图迭代一个数组,然后在每次迭代中执行 2 个步骤(我们称之为步骤 1 和步骤 2)。每次迭代之间以及步骤 1 和步骤 2 之间应该存在延迟。为了添加延迟,我使用 setTimeout() 方法。
基本上,类似于 -
对于 i 从 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 ?或者其他一些解决方案,以防我完全关闭?
最佳答案
您的问题是您正在继续第一个 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)
);
}
关于javascript - 嵌套的 setTimeout() 调用在 JavaScript 中未按正确的顺序运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55253527/