Javascript - setTimeout关闭问题

jam*_*mes 7 javascript closures for-loop blocking settimeout

我正在努力解决下面的代码.我尝试了很多不同的方法,但我最终得到了两个不正确的结果之一.

for(i = 0; i < result.length; i++) {

    var tmpBlockInfo = {
        size: worldTest.data[0].size,
        xStartPixel :  result[i].x * worldTest.data[0].size,
        yStartPixel : result[i].y * worldTest.data[0].size,
        blockType : (Math.random() * 100 > 10) ? 'path' : 'wall'
    }

    var tmpFunc = function(){
        worldTest.fillBlock(tmpBlockInfo, 157, 152, 124,  255)
    };

    var t = setTimeout(function(){
        tmpFunc()
    } , 500 * i);
}
Run Code Online (Sandbox Code Playgroud)

上面代码的问题是tmpBlockInfo总是得到最后的结果[i] .x/result [i] .y.因此,当超时运行函数时,我正在假设它看到了什么结果[i] .x/result [i] .y在循环之后保持开启(而不是将其作为"新"变量传递)

我认为将它放入函数会解决闭包问题,但没有运气.

还尝试过:

for(i = 0; i < result.length; i++) {

    var tmpBlockInfo = {
        size: worldTest.data[0].size,
        xStartPixel :  result[i].x * worldTest.data[0].size,
        yStartPixel : result[i].y * worldTest.data[0].size,
        blockType : (Math.random() * 100 > 10) ? 'path' : 'wall'
    }

    var t = setTimeout(function(){
        worldTest.fillBlock(tmpBlockInfo, 157, 152, 124,  255)
    } , 10000 * i);
}
Run Code Online (Sandbox Code Playgroud)

与第一个代码具有相同的结果.

如果我做:

for(i=0; i < result.length; i++) {

    var tmpBlockInfo = {
        size: worldTest.data[0].size,
        xStartPixel :  result[i].x * worldTest.data[0].size,
        yStartPixel : result[i].y * worldTest.data[0].size,
        blockType : (Math.random() * 100 > 10) ? 'path' : 'wall'
    }

    setTimeout(function(passBlockInfo) {
        worldTest.fillBlock(tmpBlockInfo, 157, 152, 124,  255) 
    } (tmpBlockInfo), 1000 * i);
}
Run Code Online (Sandbox Code Playgroud)

它确实正确处理所有fillBlock函数.但是它同时完成所有这些操作(例如,它不是一次一个地触发它们.它只是在彼此之后执行它们但是导致阻塞(没有屏幕更新)并且每个之间没有延迟.

任何帮助都会很棒!

Zoi*_*erg 7

原因是它正在执行它们是因为您正在执行setTimeout调用中的函数.我要做的是创建另一个这样的函数

function MakeTimeoutCall(fn, data, timeout){
    setTimeout(function() {fn.call(null, data);}, timeout);
}
Run Code Online (Sandbox Code Playgroud)

然后在你调用setTimeout的循环中,执行此操作

MakeTimeoutCall(
    function(passBlockInfo){
       worldTest.fillBlock(passBlockInfo, 157, 152, 124,  255);
    },
    tmpBlockInfo,
    1000 * i);
Run Code Online (Sandbox Code Playgroud)

(假设worldTest是一个全局对象).

这应该工作.setTimeout期待一个函数在超时结束时调用,你给你的函数,但是马上调用它.返回值(在本例中为null)将被赋予超时.所以没有超时,一切都发生了.

以防万一我的答案在上下文中有点复杂,这里是jsfiddle中一个更简单的解决方案的链接.