5

我遇到了一个问题,我的应用居住在iframe中,并且它正在从外部域中调用。当iframe加载正确时,IE9不会触发加载事件,所以我想我使用setTimeout来轮询页面。将参数传递给setTimeout的闭包

无论如何,我想看看我的setTimeout通常需要什么时间才能完成,所以我希望能够记录setTimeout从我的回调中触发的延迟,但我不确定如何将该上下文传递到所以我可以记录它。

App.readyIE9 = function() { 
    var timings = [1,250,500,750,1000,1500,2000,3000];  
    for(var i = 0; i < timings.length; i++) { 
    var func = function() { 
    if(App.ready_loaded) return; 
     console.log(timings[i]); 
     App.readyCallBack(); 
    }; 
    setTimeout(func,timings[i]); 
    } 
}; 

我不断收到日志:在IE9的控制台中未定义。

完成此操作的正确方法是什么?

感谢

+0

这可能是一个好得多的问题,如果你让它更通用,如'timing'移除这么多值和所有包含'App'的行! – cregox

回答

10

发生这种情况是因为您没有在您的func中关闭i的值。当循环完成时,i是8(timings.length),它不存在于数组中。

你需要做这样的事情:

App.readyIE9 = function() { 
    var timings = [1,250,500,750,1000,1500,2000,3000];  
    for(var i = 0; i < timings.length; i++) { 
    var func = function(x) { 
     return function(){ 
      if(App.ready_loaded) return; 
      console.log(timings[x]); 
      App.readyCallBack(); 
     }; 
    }; 
    setTimeout(func(i),timings[i]); 
    } 
}; 
+0

+1为最初正确的解决方案。 – VisioN

+0

谢谢,这正是我正在寻找的。 – user126715

+0

@ user321521:不客气:) –

10

当你的功能得到由setTimeout在将来某个时候调用的i值已经由for循环,使console.log(timings[i]);报告undefined增加它的范围的结束。

要在该函数中使用i,您需要在函数闭包中捕获它。有几种方法可以做到这一点。我会建议使用自动执行功能捕捉i这样的值:

App.readyIE9 = function() { 
    var timings = [1,250,500,750,1000,1500,2000,3000];  
    for(var i = 0; i < timings.length; i++) { 
    (function(index) { 
     setTimeout(function() { 
      if(App.ready_loaded) return; 
      console.log(timings[index]); 
      App.readyCallBack(); 
     }, timings[index]); 
    })(i); 
    } 
}; 

其位的解释谁这个工程:i传递给自动执行功能的第一个参数是功能。第一个参数被命名为index,并在每次调用自执行功能时被冻结,因此在执行setTimeout回调之前,for循环不会导致它改变。因此,在自执行函数内引用index将为每个setTimeout回调获得数组索引的正确值。

3

这是一个通常的问题,当你用setTimeoutsetInterval回调的工作。您应该i值传递给函数:

var timings = [1, 250, 500, 750, 1000, 1500, 2000, 3000], 
    func = function(i) { 
     return function() { 
      console.log(timings[i]); 
     }; 
    }; 

for (var i = 0, len = timings.length; i < len; i++) { 
    setTimeout(func(i), timings[i]); 
} 

DEMO:http://jsfiddle.net/r56wu8es/

+0

这将以'i'作为参数调用'func',并将其返回值传递给'setTimeout'。 'func'需要返回一个函数。 –

+0

@火箭。对。谢谢,纠正。 – VisioN

+0

你没有修复它。 'func'仍然返回'undefined'。 –