2

这是一个后续问题:如何暂停 JavaScript 以允许渲染

我写了一个函数来执行一种暂停的for循环(允许在两者之间进行渲染):

function loop(count, callback){
    var counter = 0
    var iteration = function(){
        callback(counter)
        counter ++;
        if (counter < count){
            setTimeout(iteration, 0)
        }
    }
    iteration();
}

这很好用,使用 eg loop(100, function(i){ console.log(i) } )。并允许浏览器在每次迭代之间进行渲染。

但是,在循环之后执行内容时会出现问题,因为不能保证循环已经完成。实际上,我认为可以保证它没有(因为在第一次调用 setTimeout 后主线程继续)。嵌套这些循环时会加剧这种情况:

loop(10, function(i){
    loop(10, function(j){
        console.log(i + '-' + j)
    })
})
/// This definitely does not output the numbers in order...

我的用例是我正在运行多个模拟,每个模拟都包含多个步骤,并且我想在每个模拟之间进行渲染。我会以错误的方式解决这个问题吗?

4

2 回答 2

2

这是我的做法:

编辑:阅读下面的 OP 评论后更新答案:

function loop(count, callback, done) {
    var counter = 0;
    var next = function () {
        setTimeout(iteration, 0);
    };
    var iteration = function () {
        if (counter < count) {
            callback(counter, next);
        } else {
            done && done();
        }
        counter++;
    }
    iteration();
}

loop(100, function (i, next) {
    console.log(i);
    next();
})


loop(10, function (i, nextI) {
    loop(10, function (j, nextJ) {
        console.log(i + '-' + j);
        nextJ();
    }, nextI);
});

输出:

1
1-1
2
1-2
3
1-3
4
1-4
5
1-5
6
1-6
7
1-7
8
1-8
9
1-9
10
11
2-1 
<< ... >>
97
98
99

http://jsfiddle.net/4Rw2H/1/

loop函数可以有第三个参数done,如果存在,它将在循环完成后运行。回调将有第二个参数next,当您想要运行下一次迭代时需要调用它。

这样,您可以在循环内调用异步函数,并且仍然让它按顺序运行。

于 2013-05-15T10:42:33.053 回答
0

这似乎工作正常:

JSFIDDLE

var log = function (i) { console.log(i) },
    loop = function (count, callback) {
        callback(count);
        count--;
        count > 0 && arguments.callee(count, callback);
    }

loop(10, log);
console.log('end');
loop(5, log);
于 2013-05-15T13:42:20.133 回答