1. 程式人生 > >js的for循環中出現異步函數,回調引用的循環值總是最後一步的值?

js的for循環中出現異步函數,回調引用的循環值總是最後一步的值?

-m tor 都是 lock 也會 console 就是 代碼 自帶

這幾天跟著視頻學習node.js,碰到很多的異步函數的問題,現在將for循環中出現的異步函數回調值的問題總結如下:

具體問題是關於遍歷文件夾中的子文件夾的,for循環包裹異步函數的代碼:

for (var i = 0; i < files.length; i++) {
    var itemFile = files[i];
    fs.stat("./uploads/" + itemFile, function (err, stats) {    
        if (stats.isDirectory()) {
            console.log(itemFile+i);    
        } else {
            console.log(2);
        }
    });
}

輸出結果是:

wedding3
wedding3
wedding3

for循環是同步任務,i在不斷滴增加直到等於file.length時候,循環不再執行,即等於3(自己實驗代碼)。而循環內部的判斷是否是文件夾的isDirectory函數是異步函數,也就是說內部的console.log(itemFile+i); 的執行任務被排在了任務隊列的最後,所以for循環本身會先執行3次,但是不執行回調裏面的任務,for循環都結束時,回調函數裏面的console.log才開始執行第一次,所以每次輸出都是wedding3.

當然這並不是我們想要的結果,解決方法可以通過自執行函數傳參(匿名函數),這樣就形成了不受外界變量影響的局部作用域。如:

for (var i = 0; i < files.length; i++) {
    (function(i){
        var itemFile = files[i];
        fs.stat("./uploads/" + itemFile, function (err, stats) {    
            if (stats.isDirectory()) {
                console.log(itemFile+i);    
            } else {
                console.log(2);
            }
        });
    })(i);  
}

輸出得到:

cat0
dog1
wedding2

這樣就可以解決之前只輸出最後循環的值的問題。

前端頁面開發也會碰到類似的問題,比如setTimeout異步執行的問題,在前端可以通過jquery的each方案解決。用jQuery的 $.each(),自帶回調函數,形成了函數作用域.

<script type="text/javascript">
    var arr = ["dog",cat","wedding"];
    $.each(arr, function(key, value) {
        setTimeout(function() {
            console.log(key);
            console.log(value);
        }, 2000);
    });
</script>

js的for循環中出現異步函數,回調引用的循環值總是最後一步的值?