如何在JavaScript中使用递归函数时处理promise

时间:2018-05-13 08:48:25

标签: javascript node.js es6-promise

我想以递归方式记录目录中的所有文件,并在记录所有文件时返回确认。这是目录结构。

sample │ app.js └───Temp1 │ │ temp1.js │ └───Temp2 │ │ temp2.js

这是代码

```

let readDirectory = function(dirname){
    return new Promise((resolve,reject)=>{
         fs.readdir(dirname,(err,files)=>{
            if(err) reject(err);
            files.forEach(file=>{
                fs.stat(`${dirname}/${file}`,(err,stats)=>{
                    if(stats.isDirectory()){
                        readDirectory(`${dirname}/${file}`)
                    }else{
                        resolve(console.log(file));                      
                    }
                })                
            })
        })
    })   
}



readDirectory(sampledir).then(()=>console.log('completed'));

```

以下是执行此功能时的结果。

```

app.js
completed
temp1.js
temp2.js

```

我应该在哪里解决以获得如下输出。

```

app.js
temp1.js
temp2.js
completed

```

1 个答案:

答案 0 :(得分:3)

只有在Promise.all解析每个文件后才需要解决。此外,只有在目录中的每个文件完成后才需要解析每个目录promise:

let readDirectory = function(dirname) {
  return new Promise((resolveAll, rejectAll) => {
    fs.readdir(dirname, (err, files) => {
      if (err) rejectAll(err);
    })
  }).then((files) => {
    const filesPromises = files.map(file => (
      new Promise((resolveFile, rejectFile) => {
        fs.stat(`${dirname}/${file}`, (err, stats) => {
          if (err) rejectFile(err);
          if (stats.isDirectory()) {
            readDirectory(`${dirname}/${file}`)
             .then(resolveFile);
             .catch(rejectFile);
          } else {
            resolveFile(console.log(file));
          }
        })
      })
    ));
    return Promise.all(filesPromises).then(resolveAll);
  });
}

请注意,非常难以理解 - 使用async / await会更好,而不是这样:

let readDirectory = async function(dirname) {
  const files = await new Promise((resolve, reject) => {
    fs.readdir(dirname, (err, files) => {
      if (err) reject(err);
      resolve(files);
    });
  });
  const filesPromises = files.map(async (file) => {
    const stats = await new Promise((resolve, reject) => {
      fs.stat(`${dirname}/${file}`, (err, stats) => {
        if (err) reject (err);
        else resolve(stats);
      });
    });
    if (stats.isDirectory()) await readDirectory(`${dirname}/${file}`);
    else console.log(file);
  });
  return Promise.all(filesPromises);
}