Как обрабатывать обещания при использовании рекурсивных функций в JavaScript - PullRequest
0 голосов
/ 13 мая 2018

Я хочу записать все файлы в каталоге рекурсивно и вернуть подтверждение, когда все файлы будут зарегистрированы.Вот структура каталогов.

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

` ``

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Если вы используете Узел 8 или новее, вы можете пообещать улучшить читаемость:

const util = require('util')
const fs = require('fs')

const stat = util.promisify(fs.stat)
const readdir = util.promisify(fs.readdir)

let readDirectory = (dirname) =>
    readdir(dirname).then(files =>
      Promise.all(files.map(file =>
          stat(`${dirname}/${file}`).then(stats =>
            stats.isDirectory() ? readDirectory(`${dirname}/${file}`) :
            console.log(file)
          )
      ))
    )

readDirectory(__dirname).then(() => {
    console.log('Completed')
})

Или супер упрощенную версию с асинхронным / ожидающим :

let readDirectory = async dirname =>
    await Promise.all((await readdir(dirname)).map(async file =>
       (await stat(`${dirname}/${file}`)).isDirectory() ?
            readDirectory(`${dirname}/${file}`) : console.log(file)
    ))
0 голосов
/ 13 мая 2018

Необходимо разрешить только после Promise.all разрешения по каждому файлу.Кроме того, вам нужно разрешать каждое обещание каталога только после того, как каждый файл в каталоге завершен:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...