循环中的setTimeout并传递变量以供以后使用

时间:2013-01-10 17:39:12

标签: javascript

请考虑以下代码:

function func() {
    var totalWidths = 0;
    for( var i = 0, count = arr.length; i < count; i++ ) {
        var image = arr[i];

        insertElemInDOM(image);

        preloadImage(image,function(){
            var w = image.width();
            totalWidths += w;
        });

    }
    // do something with the variable "totalWidths"
    doSomething(totalWidths)
}

我这里有两个问题。图像将始终相同(第一个问题),可以使用匿名函数解决:

    for(...) {
        (function(image) {
            preload(image,function() {
                // now image is the correct one
            });
        })(image);
    }

但是我如何管理totalWidths变量以便稍后在doSomething(totalWidths)上使用它?对于totalWidth,前面的代码的值为0。 谢谢!

1 个答案:

答案 0 :(得分:2)

你可以超时整个循环和doSomething,这比设置这么多超时要高得多:

setTimeout(function() {
    var inc = 0;
    for (var i = 0; i < count; i++) {
        var w = arr[i].width();
        inc++;
    }
    doSomething(inc);
}, 1000);

但是,您实际上想要的是嵌套超时,即每次迭代步骤等待1秒,并在完成后执行某些操作:

var inc = 0, count;
function asyncLoop(i, callback) {
    if (i < count) {
        var w = arr[i].width();
        inc++;
        setTimeout(function() {
            asyncLoop(i+1, callback);
        }, 1000);
    } else {
        callback();
    }
}
asyncLoop(0, function() {
    doSomething(inc);
});

好了,现在我们知道你需要的解决方案是在每次加载事件后检查是否所有图像都已加载:

var totalWidths = 0,
    count = arr.length,
    loaded = 0;
for (var i = 0; i < count; i++) 
    (function (image) {
        insertElemInDOM(image);
        preload(image, function() {
            totalWidths += image.width();
            // counter:
            loaded++;
            if (loaded == count-1) // the expected value
                doSomething(totalWidths); // call back
        });
    })(arr[i]);