2016-12-20 14 views
1

我想列出目录中的所有文件夹以及最后列出的文件夹数量。这个fs.readdir函数中的竞态条件在哪里?

这是我的代码:

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); 
      } 
     }); 
    } 
}); 

代码应该:

  1. 阅读目录
  2. 增量count为每个文件夹目录
  3. 当目录读取完毕之后,日志'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 

在哪里竞争条件发生了什么?

回答

1

我意识到竞赛情况的发生,因为i可以在所有fs.stat s完成执行之前完成递增,因为它在fs.stats的回调之外递增。

因此,我需要一个单独的变量(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