Javascript - setTimeout 关闭问题

标签 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 * 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 总是得到最后的 result[i].x/result[i].y。所以我假设当超时运行函数时,它会看到循环后留下了什么 result[i].x/result[i].y(而不是将其作为"new"变量传递)

我认为将它放入函数中可以解决闭包问题,但没有成功。

也试过:

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 函数。但是它同时执行所有操作(例如,它不是一次触发一个。它只是一个接一个地执行它们,但会导致阻塞(没有屏幕更新)并且每个操作之间没有延迟。

任何帮助都会很棒!

最佳答案

之所以立即执行它们,是因为您正在执行 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 中更简单解决方案的链接。

关于Javascript - setTimeout 关闭问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9485270/

相关文章:

javascript - 将 JS Regex 捕获组存储在数组中的最佳方式?

mysql - 如何使用 for 循环将新字段添加到文档索引 Lucene 中。

closures - 我可以创建一个 "unsafe closure"吗?

javascript - 触发事件来调用闭包内的函数

Javascript 闭包 - 父函数

javascript - 原因 : `object` ("[object Date]") cannot be serialized as JSON. 请只返回 JSON 可序列化数据类型

javascript - Phantomjs 进程间通信

c - 优化 C 中的嵌套循环

c++ - 在 c++ 中的 unordered_map 中仅访问一对元素中的一个元素

javascript - 拖动 UI 输入范围 slider 的范围