我在类中有以下代码. (这是coffeescript–它是一个couchdb实用程序! – 但这确实是一个node.js问题).我正在尝试使用Node 0.49做Node Node,这意味着使用异步调用来进行文件系统操作.起初,我正在把头发拉出来,因为这个过程在处理过程中几次变为零,所以我知道我在那里做错了.但后来我遇到了一个更棘手的问题:在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,files) => for fname in files console.log("X1: ",fname) fs.stat path.join(dirpath,fname),stats) => console.log("X2: ",fname) if stats.isFile() @load_file(dirpath,fname,object) if stats.isDirectory() object[fname] = {} @load_directory(path.join(dirpath,object[fname]) @check_sentinel()
这是我得到的:
X1: memberByName.js X1: memberByClub.js X2: memberByClub.js X2: memberByClub.js
这是超现实的,它看起来很像竞争条件. “memberByName”被传递给fs.stat(),后者又将“memberByClub”传递给load_file(),暗示……什么?那是因为load_file()立即返回,它绕过并将数组中的下一个文件名提供给函数调用?或者我对给定范围内的值的持久性有一些误解?
解决方法
不,你看到的是预期的.你必须记住的一件事是fs.stat是异步的.因此,外部循环(对于文件中的fname)将在调用fs.stat的任何回调之前完成循环.
你看到memberByClub.js两次的原因是你在logging语句中使用fname,但是该变量来自闭包,它在你调用fs.stat的回调时已经改变了.
你可以使用do(fname)=>包装内部循环.获取正确的日志记录语句,但我认为您需要重新构建代码以实现您尝试对整个类进行的操作.
load_directory: (dirpath,files) => for fname in files do (fname) => console.log("X1: ",fname) fs.stat path.join(dirpath,stats) => console.log("X2: ",fname) if stats.isFile() @load_file(dirpath,object) if stats.isDirectory() object[fname] = {} @load_directory(path.join(dirpath,object[fname]) @check_sentinel()