这几天跟着视频学习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); ???????} ???});}
输出结果是:
wedding3wedding3wedding3
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); ?}
输出得到:
cat0dog1wedding2
这样就可以解决之前只输出最后循环的值的问题。
前端页面开发也会碰到类似的问题,比如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>