Javascript-设置超时关闭问题

Javascript-设置超时关闭问题,javascript,for-loop,closures,settimeout,blocking,Javascript,For Loop,Closures,Settimeout,Blocking,我正在努力处理下面的代码。我尝试了很多不同的方法,但最终得到了两个错误结果中的一个 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 * worldTe

我正在努力处理下面的代码。我尝试了很多不同的方法,但最终得到了两个错误结果中的一个

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);
}
for(i=0;i10)?“路径”:“墙”
}
var tmpFunc=函数(){
worldTest.fillBlock(tmpBlockInfo,157152124255)
};
var t=setTimeout(函数(){
tmpFunc()
},500*i);
}
上面代码的问题是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);
}
for(i=0;i10)?“路径”:“墙”
}
var t=setTimeout(函数(){
worldTest.fillBlock(tmpBlockInfo,157152124255)
},10000*i);
}
与第一个代码的结果相同

如果我这样做:

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);
}
for(i=0;i10)?“路径”:“墙”
}
设置超时(函数(passBlockInfo){
worldTest.fillBlock(tmpBlockInfo,157152124255)
}(tmpBlockInfo),1000*i);
}
它确实正确处理所有fillBlock函数。但它同时执行所有这些操作(例如,它不是一次触发一个,而是一个接一个地执行,但会造成阻塞(无屏幕更新)和每个操作之间没有延迟)


这方面的任何帮助都会很好!

之所以立即执行它们,是因为您正在执行setTimeout调用中的函数。我要做的是创建另一个这样的函数

function MakeTimeoutCall(fn, data, timeout){
    setTimeout(function() {fn.call(null, data);}, timeout);
}
然后在调用setTimeout的循环中,执行以下操作

MakeTimeoutCall(
    function(passBlockInfo){
       worldTest.fillBlock(passBlockInfo, 157, 152, 124,  255);
    },
    tmpBlockInfo,
    1000 * i);
(假设worldTest是一个全局对象)

这应该行得通。setTimeout期望函数在超时结束时调用,您给出的是函数,但立即调用它。返回值(在本例中为null)将被提供给超时。因此没有超时,所有事情都会立即发生

为了防止我的答案在上下文中有点复杂,我在JSFIDLE中提供了一个指向更简单解决方案的链接。

试试以下方法:

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(createFillBlockFn(tmpBlockInfo) , 500 * i);
}

function createFillBlockFn(blockInfo) {
    return function() {
        worldTest.fillBlock(blockInfo, 157, 152, 124,  255)
    }
}
for(i=0;i10)?“路径”:“墙”
}
var t=设置超时(createFillBlockFn(tmpBlockInfo),500*i);
}
函数createFillBlockFn(blockInfo){
返回函数(){
worldTest.fillBlock(blockInfo,157152124255)
}
}

您需要一个包装函数来保留作用域。这只是实现这一点的几种方法之一

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

    setTimeout(function () {

        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'
        };

       return function () {
           worldTest.fillBlock(tmpBlockInfo, 157, 152, 124,  255);
       };
    }(), 1000 * i);
}
for(i=0;i10)?“路径”:“墙”
};
返回函数(){
fillBlock(tmpBlockInfo,157152124255);
};
}(),1000*i);
}

此代码将帮助您:

for(i=0; i < result.length; i++)
{
    setTimeout(function(){
        {
            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'
        }, 157, 152, 124,  255);
    } , 500 * i);
}
for(i=0;i10)?“路径”:“墙”
}, 157, 152, 124,  255);
},500*i);
}

变量在函数顶部声明,因此您有一个变量tmpBlockInfo、ont tmpFunc和您重新分配的那些变量。

p.S.请确保使用var来限定i变量的范围,否则它将被视为全局变量,没有什么比全局循环变量更危险的了,因为它会导致难以调试的错误。您好,谢谢你的回复!我刚刚尝试过这个,但是我遇到了与上面代码1和代码2示例相同的问题。从这里我可以告诉你,这只是我在代码示例1和2中所做的另一种方式?我忘记了超时中的*I,让我来解决这个问题。啊,刚刚更改了I变量的范围。我想这就是问题所在!但是没有运气!由于传递给
MakeTimeoutCall
的函数忽略传递给
passBlockInfo
参数的参数,而是使用原始的
tmpBlockInfo
,因此代码无法工作。我认为您可能有点过于复杂了。尽管这是一个常见的问题,+1表示您已多次尝试解决此问题……您上次的尝试非常接近,但您需要返回一个运行代码的函数,以便
setTimeout
以后可以运行它,您需要使用
passBlockInfo
参数,而不是
tmpBlockInfo
这是一种很好的方法。唯一的缺点是JSLint会抱怨它,但再一次,JSLint只是喜欢伤害人们的感情。@amnotiam:i的值在闭包内会不总是一样吗?这似乎并没有解决c语言中臭名昭著的循环问题