2013-01-10 31 views
0

考慮下面的代碼:的setTimeout在一個循環和傳遞變量使用後

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) 
} 

我在這裏有2個問題。圖像將始終是相同的(第一個問題),其中一個可以用匿名函數解決:

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

但我怎麼才能在以後使用它的doSomething(totalWidths)管理totalWidths變量?以前的代碼對於totalWidths的值爲0。 謝謝!

+3

? –

+0

@Diodeus:我猜測代碼執行時DOM元素不存在。因此,檢查元素的寬度必須被延遲。 – Amberlamps

+0

這是真的!這正是問題 – Jonas

回答

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

OK,現在我們知道你需要什麼解決的辦法是每個負載事件之後檢查所有圖像是否已加載:爲什麼你需要擺在首位此計時器

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]); 
+0

我需要setTimeout的另一個原因只是爲了獲取元素的寬度。 – Jonas

+3

如果這是一個加載節點問題,請使用'load'事件 – kidwon

+0

更確切地說:這段代碼只是一個簡單的例子。我面臨的真正問題是我在DOM中插入元素/圖像,setTimeout(在我的情況下是圖像預加載函數)用於計算預加載後圖像的寬度。我希望這是有道理的..:S – Jonas