我一直在查看关于setTimeout()和循环延迟的许多SO帖子,但是还没有找到一个可行的解决方案。我正在浏览器中对一些数据进行动画演示,我需要多次重绘相同的序列,事件按特定顺序发生,包括带有延迟的内部循环。像这样:
for (var pass = 1; pass <= passes; pass++) {
// 1. Prep some data, update DOM (must happen *before* inner loop)
// 2. Run inner loop with delays (multiple DOM updates...)
(function loopWithDelay() {
setTimeout(function() {
// Iterate on data
// Update DOM on each iteration
if ( !condition() ) {
loopWithDelay();
}
}, 250); // delay at each iteration
})();
// 3. Do wrap-up calcs, update DOM (must happen *after* above loop)
} // If more passes remain, repeat..
所以,我能够延迟内循环的迭代(第2部分),但是因为它是非阻塞的,所以第3部分立即执行,因此父循环不能正常工作。我有点理解Javascript的异步/非阻塞性质,但不能完全理解如何干净地完成这样的多序列(或实际上让它完全工作!)会喜欢这个特殊情况的一些建议。
答案 0 :(得分:1)
如果您想使用异步方法,您的设计需要更改为event-driven而不是结构化。
基本上,您需要使用callback
来处理延迟(如果您想要前沿,则需要使用Prom:D)
我在想这样的事:
(function() {
var after_loop = function() {
// Move 3 here
// 3. Do wrap-up calcs, update DOM (must happen *after* above loop)
}
var loopWithDelay = function() {
// update whatever DOM you want
updateDom();
// Check if we need to stop the looping
if (stop_condition) {
clearInterval(interval);
after_loop();
}
}
var interval = setInterval(loopWithDelay, 250);
})();
loopWithDelay
将每250毫秒调用一次,当stop_condition
为真时,它将停止运行并运行after_loop();
答案 1 :(得分:1)
这样做(我称之为回调循环):
function outerloop(pass, passes) {
if (pass > passes) return;
// 1. Prep some data, update DOM (must happen *before* inner loop)
// 2. Run inner loop with delays (multiple DOM updates...)
(function loopWithDelay() {
setTimeout(function () {
// Iterate on data
// Update DOM on each iteration
if (!condition()) {
loopWithDelay();
} else {
outerloop(pass++, passes);
}
}, 250); // delay at each iteration
})();
// 3. Do wrap-up calcs, update DOM (must happen *after* above loop)
}
outerloop(1, passes);
答案 2 :(得分:0)
这样的事可能......?
var states = {
beforeLoop: 0,
innerLoop: 0,
afterLoop: 0
};
var timeouts = {
beforeLoop1: undefined,
beforeLoop2: undefined,
innerLoop1: undefined,
innerLoop2: undefined,
afterLoop1: undefined,
afterLoop2: undefined
}
function setTimeoutType(fun,time,type){
states[type]++;
return setTimeout(fun,time);
}
function mainLoop(){
if(beforeLoop1 == undefined)
beforeLoop1 = setTimeoutType(beforeFun1,1000,'beforeLoop');
if(beforeLoop2 == undefined)
beforeLoop2 = setTimeoutType(beforeFun2,1000,'beforeLoop');
if(states.beforeLoop == 0){
if(innerLoop1 == undefined)
innerLoop1 = setTimeoutType(innerFun1,1000,'innerLoop');
if(innerLoop2 == undefined)
innerLoop2 = setTimeoutType(innerFun2,1000,'innerLoop');
if(states.innerLoop == 0){
if(afterLoop1 == undefined)
afterLoop1 = setTimeoutType(afterFun1,1000,'afterLoop');
if(afterLoop2 == undefined)
afterLoop2 = setTimeoutType(afterFun2,1000,'afterLoop');
if(states.afterLoop == 0){
// loops done
}
else setTimeout(mainLoop,1000);
}
else setTimeout(mainLoop,1000);
}
else setTimeout(mainLoop,1000);
}
function beforeFun1(){
// code
states.beforeLoop--;
}
function beforeFun2(){
// code
states.beforeLoop--;
}
function innerFun1(){
// code
states.innerLoop--;
}
function innerFun2(){
// code
states.innerLoop--;
}
function afterFun1(){
// code
states.afterLoop--;
}
function afterFun2(){
// code
states.afterLoop--;
}
function startThisHugeThing(){
timeouts = {
beforeLoop1: undefined,
beforeLoop2: undefined,
innerLoop1: undefined,
innerLoop2: undefined,
afterLoop1: undefined,
afterLoop2: undefined
}
setTimeout(mainLoop,1000);
}