我在类中有以下代码。 (这是coffeescript--它是一个couchdb实用程序! - 但这确实是一个node.js问题)。我正在尝试使用Node 0.49做Node Node,这意味着使用异步调用来进行文件系统操作。起初,我正在拔头发,因为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()
,后者又将“memberByClub”传递给load_file()
,暗示......什么?那是因为load_file()
立即返回,它在数组中运行并向函数调用提供了下一个文件名?或者我对给定范围内的值的持久性有一些误解?
答案 0 :(得分:8)
不,你看到的是预期的。您必须记住的一件事是fs.stat
是异步的。因此,外部循环(for fname in files
)将在调用fs.stat
的任何回调之前完成循环。
您看到memberByClub.js
两次的原因是您在日志记录语句中使用fname
,但该变量来自闭包,该回调在回调到{{1}时已更改被称为。
您可以使用fs.stat
包装内部循环以获取正确的日志记录语句,但我认为您需要重新构建代码以实现您尝试对整个类进行的操作。
do (fname) =>