这个fs.readdir函数中的竞态条件在哪里?
我想列出一个目录中的所有文件夹,并在结尾列出有多less个文件夹。
这是我的代码:
fs.readdir(dir, (err, folders) => { if (err) return console.log(err); let count = 0; for (let i = 0; i < folders.length; i++) { let folder = folders[i]; fs.stat(dir + '/' + folder, (err, stats) => { if (err) return console.log(err); if (stats.isDirectory()) { console.log(folder); count++; } if (i >= (folders.length - 1)) { console.log('folders: ' + count); } }); } });
代码应该:
- 阅读目录
- 目录中每个文件夹的递增
count
- 当目录读取完成后,logging
'folders: ' + count
在大多数情况下,这个工作,我得到这个:
... 2016-12-20--09-59-12 2016-12-20--09-59-13 2016-12-20--09-59-14 folders: 86
有时候,虽然我得到这个:
... 2016-12-20--09-59-12 2016-12-20--09-59-11 2016-12-20--09-59-14 folders: 85 2016-12-20--09-59-13
竞赛状况在哪里发生?
我意识到竞赛情况的发生,因为i
可以在所有的fs.stat
完成执行之前完成递增,因为它在fs.stats
的callback之外递增。
因此,我需要一个单独的variables( j
)来跟踪所有fs.stats
的完成,只有当这些完成递增时,我才能列出count
。
这里是正确的代码:
fs.readdir(dir, (err, folders) => { if (err) return console.log(err); let count = 0, j = 0; // this bad boy! for (let i = 0; i < folders.length; i++) { let folder = folders[i]; fs.stat(dir + '/' + folder, (err, stats) => { if (err) return console.log(err); j++; // j, unlike i, only gets incremented *inside* the async function if (stats.isDirectory()) { console.log(folder); count++; } if (j >= folders.length) { // check j, not i console.log('folders: ' + count); } }); } });
现在输出一致:
... 2016-12-20--09-59-13 2016-12-20--09-59-11 2016-12-20--09-59-14 folders: 86