node.js中的异步目录遍历中需要注意的问题

<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="javascript">var path = require("path");<pre name="code" class="javascript">var fs = require("fs");

 
 

function travelDir( dir, callback ) {
	fs.readdirSync( dir ).forEach( function( file) {
		var pathname = path.join( dir, file );
		if( fs.statSync( pathname ).isDirectory() ) {
			travelDir( pathname, callback );
		}else {
			callback( pathname );
		}
	} );
}
function travelDirAsync( dir, callback, finish ) {
	fs.readdir( dir, function( error, files ) {
		if ( files ) {
			( function next( i ) {
				if ( i < files.length ){
					console.log("i=" + i);
					console.log(files);
					var pathname = path.join( dir, files[i] );
					fs.stat( pathname, function( error, stat ) {
						if ( stat ){
							if ( stat.isDirectory() ) {
								travelDirAsync( pathname, callback, function() {
									next( i + 1 );
								} );
							} else {
								callback( pathname, function(){
									next( i + 1 );
								} );
							}
						} else {
							console.log( error.name + ":" + error.message );
						}
					} );
				} else {
					// 注意运行上下文
					finish && finish();
				}
			}( 0 ) );
		} else {
			console.log( error.name + ":" + error.message );
		}
	} );
}

function main( argv ) {
	//sync
	/*
	travelDir( argv[0], function( pathname ) {
		if( path.extname( pathname ) == ".js" ) {
			console.log( pathname );
		}
	} );
	*/
	//async
	travelDirAsync( argv[0], function( pathname,next ) {
		console.log( pathname );
		next();
	}, function() {
		console.log("visiting finished.");
	} );
}
main( process.argv.slice(2) );

从昨天开始学node.js。这段代码摘自学习中看到的一篇博客,稍作修改,思想上是一样的。
光是理解travelDirAsyn这个方法里代码就花去了3小时的人生,我始终没有弄明白finish函数的意义。一度看的抓狂。最后向我的一个朋友求助后终于弄明白了。

究其原因还是自己在遍历目录上有种思维定式(来源于其他的编程语言,例如java和c)。一开始我总是在那边想这代码是怎么在进入一层目录后返回到上一层目录的呢?看了无数遍的代码也没想明白。
后来朋友跟我说callback函数中的变量i 和 finish函数中的变量i 并不是同一个 i 的时候就恍然大悟了。
原来因为之前的思维定式,忘记了在js里还有运行上下文这东西。每次函数执行的时候都会创建一个运行上下文,保存其中的变量。
假设有遍历的根目录是test
目录层次为:
-test
	a.js
	b.js
	-folder
		a.txt
		b.txt
	c.js

那么在第一次运行遍历函数travelDirAsyn时,创建了一个运行上下文。其中i的初始值为0,files的值为['a.js','b.js','folder','c.js']。遍历到folder的时候i的值为2。再一次运行travelDirAsyn进入folder目录,又创建了一个新的运行上下文。遍历两次后当前运行上下文的i的值为2,if条件不成立跳到else执行finish函数。此时finish函数的执行环境位于之前的运行上下文(因为finish函数最近一次绑定位于之前的运行上下文),执行next( i + 1 ),之前的运行上下文中的 i 的值为2,所以此时执行的也就是 next(3)。最后输出c.js。

新手请多包涵,个人见解,有错欢迎指出。
大家可以复制代码自己运行试试。
命令行:node xxx.js 目录地址


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值