我正在努力解决以下代码问题。我尝试了很多不同的方法,但我最终得到了两个不正确的结果之一。
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);
}
上面代码的问题是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; 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);
}
它会正确处理所有fillBlock函数。但它同时完成所有这些操作(例如,它不是一次一个地触发它们。它只是在彼此之后执行它们但导致阻塞(没有屏幕更新)并且每个之间没有延迟。
任何帮助都会很棒!
答案 0 :(得分:7)
原因是它正在执行它们是因为您正在执行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)将被赋予超时。所以没有超时,一切都会立刻发生。
考虑到上下文,我的答案有点复杂,here是jsfiddle中更简单解决方案的链接。
答案 1 :(得分:4)
试试这个:
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)
}
}
答案 2 :(得分:0)
您需要一个包装函数来保留范围。这只是少数几种方法之一。
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);
}
答案 3 :(得分:0)
此代码可以帮助您:
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);
}
变量在函数的顶部声明,因此你有一个var tmpBlockInfo,ont tmpFunc,以及那些你重新分配的变量。