2016-08-10 112 views
0

我想監視一個for循環每X毫秒的內容:如何監控for-loop?

下面是一個例子,我希望看到進展的百分比每0.1秒時:

for (i = 0, max = 9007199254740992, timer = setInterval(function() {console.log(100*i/max);}, 100); i < max; i++) { 
    // something 
} 
clearInterval(timer); 

但它沒有做任何輸出。

我不想在我的循環中添加一個測試,以避免使用無用的計算時間。

+2

For循環將在100ms內完成 –

+0

@RajaprabhuAravindasamy - 我完全沒有做循環,但'循環中'初始化' – Rayon

+1

''setInterval'的回調函數將在'duration'後被調用,如顯式調用'clearInterval'在'100ms'之前調用,''callback'永遠不會被調用。 – Rayon

回答

6

由於Javascript的單線程特性,無論執行多長時間,您的setInterval()回調都不可能在for循環結束之前調用。

我建議以相反的方式來做:每N次迭代記錄已用時間。

var res = [], 
 
    ts = performance.now(); 
 

 
for(var i = 0, max = 1E6; i < max; i++) { 
 
    if(!(i % 10000)) { 
 
    res.push(performance.now() - ts); 
 
    } 
 
    // do something 
 
} 
 

 
console.log(res);

或者:

var res = [], 
 
    ts = performance.now(); 
 

 
for(var i = 0, iMax = 1E6; i < iMax; i += 10000) { 
 
    for(var j = i, jMax = Math.min(i + 10000, iMax); j < jMax; j++) { 
 
    // do something 
 
    } 
 
    res.push(performance.now() - ts); 
 
} 
 

 
console.log(res);

如果你真的想登錄實時,你必須得到控制後,各瀏覽器一批N次迭代。性能方面,這可能會產生重大影響。

var res = [], 
 
    ts = performance.now(); 
 

 
function processBatch(i, iMax, sz) { 
 
    for(var j = i, jMax = Math.min(i + sz, iMax); j < jMax; j++) { 
 
    // do something 
 
    } 
 
    console.log((j * 100/iMax) + '%', (performance.now() - ts).toFixed(2) + 'ms'); 
 

 
    if(j < iMax) { 
 
    setTimeout(function() { processBatch(j, iMax, sz); }, 0); 
 
    } 
 
} 
 

 
processBatch(0, 1E6, 10000);

編輯:這第三種方法顯著更新。以前的版本是錯誤的。

+1

你對它未被調用的原因是正確的,但OP表示他們不想在循環中做一個測試「以避免使用無用的計算時間」。也許在外循環中使用嵌套循環?或者網絡工作者(雖然看起來過於複雜)? – samgak

+1

@samgak你說得對。但是,任何措施都會改變結果。不過,我已經添加了一個備用方法。 – Arnauld

+1

如果(!(i&mask)){與%8192相同,則可以通過使用位掩碼獲得比模數更便宜的方式:'mask =(1 << 13)-1''缺點:你必須堅持2的冪。如果'max%10000!= 0'更好,你的第二次嘗試將會過沖,因爲(var i = 0,max = 1E6; i Thomas