Node.js和文件系统:这是一个竞争条件?

我有一个类内的以下代码。 (这是coffeescript – 这是一个couchdb实用程序! – 但这真的是一个node.js问题)。 我正在尝试使用节点0.49来执行节点方法,这意味着使用asynchronous调用进行文件系统操作。 起初,因为这this.sentinel在加工过程中几次this.sentinel ,所以我知道自己在那里做错了事。 但是,然后我碰到一个更奇怪的问题:在load_directory下,看到这些console.log()调用? 当我运行这个时,看看什么时候发生

 check_sentinel: -> @sentinel-- if @sentinel == 0 @emit('designDirLoaded', @object) load_file: (rootdir, filename, object) -> @sentinel++ fname = path.join(rootdir, filename) @manifest.push(fname) fs.readFile fname, (err, data) => object[filename] = data @check_sentinel() load_directory: (dirpath, object) -> @sentinel++ fs.readdir dirpath, (err, files) => for fname in files console.log("X1: ", fname) fs.stat path.join(dirpath, fname), (err, stats) => console.log("X2: ", fname) if stats.isFile() @load_file(dirpath, fname, object) if stats.isDirectory() object[fname] = {} @load_directory(path.join(dirpath, fname), object[fname]) @check_sentinel() 

这是我得到的:

 X1: memberByName.js X1: memberByClub.js X2: memberByClub.js X2: memberByClub.js 

这是超现实的,它看起来很像一个竞争条件。 “memberByName”传递给fs.stat() ,而fs.stat()又传递“memberByClub”到load_file load_file() ,意味着什么? 那是因为load_file()立即返回,它跑来跑去,并将数组中的下一个文件名称呈现给函数调用? 还是我对某个范围内的价值观的持续存在误解?

不,你所看到的是预期的。 有一件事你必须记住的是, fs.stat是asynchronous的。 所以,在调用fs.stat任何callback之前,外层循环( for fname in files )将会结束循环。

你看到memberByClub.js两次的原因是你在logging语句中使用了fname ,但是这个variables来自于闭包,当你调用fs.stat的时候,这个variables已经改变了。

你可以用do (fname) =>来包装内部循环来获得正确的日志语句,但是我认为你需要重构你的代码来实现你正在试图用整个类来做的事情。

 load_directory: (dirpath, object) -> @sentinel++ fs.readdir dirpath, (err, files) => for fname in files do (fname) => console.log("X1: ", fname) fs.stat path.join(dirpath, fname), (err, stats) => console.log("X2: ", fname) if stats.isFile() @load_file(dirpath, fname, object) if stats.isDirectory() object[fname] = {} @load_directory(path.join(dirpath, fname), object[fname]) @check_sentinel()