js的for循環中出現異步函數,回調引用的循環值總是最後一步的值?
阿新 • • 發佈:2017-12-11
-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循環中出現異步函數,回調引用的循環值總是最後一步的值?