如何使用Promise来使此代码正常工作?

时间:2019-05-15 01:27:51

标签: javascript node.js recursion promise

我想使用then(),如下所示,在我的代码完成了递归文件夹层次结构之后。

一切正常,尤其是

的使用
  const fileNames = await fs.promises.readdir(dir);

  const stat = await fs.promises.stat(thing_path);

但是,递归部分我不知道该如何正确实现

getFolderInfo(start).then((all_data)=>{
  console.log('Done recursing the directory');  
});

正常工作。

完成文件

const fs = require('fs');
const path = require('path');

// Configure & Initialize
let start = '_t/';
let depth = 1;
let counter = 0;
let total_size = 0;

// Definition
async function recurseFolders(dir, callback) {
  const fileNames = await fs.promises.readdir(dir);
  const listings = await Promise.all(
    fileNames.map(async (thing_name) => {
      const thing_path = path.join(dir, thing_name);
      const stat = await fs.promises.stat(thing_path);
      return {name: thing_name, path: thing_path, size: stat.size, isFolder: stat.isDirectory()};
    })
  );
  listings.forEach(iterate);
  function iterate (listing) {
    counter++;
    total_size += listing.size;
    listing.counter = counter;
    listing.total_size = total_size;
    callback(listing);
    if (listing.isFolder) {
      recurseFolders(listing.path, callback);
    }
  }
}

async function getFolderInfo (start) {
  await recurseFolders(start, (data) => {
    console.log(data);
  });
}

getFolderInfo(start).then((all_data)=>{
  console.log('Done recursing the directory');  
});

3 个答案:

答案 0 :(得分:1)

如果将fs工作放到其自己的功能中,则问题可以很好地解决。此函数在给定路径上运行stat,并为每个条目回答修改后的stat对象...

async function getStats(path) {
  const names = await fs.promises.readdir(path);
  let promises = names.map(async name => {
      const pathName = path.join(path, name)
      const stat = await fs.promises.stat(pathName);
      return { name: name, path: pathName, size: stat.size, isFolder: stat.isDirectory() };
  })
  return await Promise.all(promises)
}

现在,只需为给定路径调用getStats,将回调应用于每个结果,然后对包含的目录进行递归或不执行任何操作...

async function recurseFolders(path, callback) {
    const stats = await getStats(path)
    let promises = stats.map(async stat => {
        callback(stat)
        return await stat.isFolder ? recurseFolders(stat.path, callback) : Promise.resolve()
    })
    return await Promise.all(promises)
}

就是这样。

答案 1 :(得分:0)

var fs = require('fs');
var path = require('path');
var getFolderInfo = function (dir, done) {
    var results = [];
    fs.readdir(dir, function (err, list) {
        if (err) return done(err);
        var pending = list.length;
        if (!pending) return done(null, results);
        list.forEach(function (file) {
            file = path.resolve(dir, file);
            fs.stat(file, function (err, stat) {
                if (stat && stat.isDirectory()) {
                    getFolderInfo(file, function (err, res) {
                        results = results.concat(res);
                        if (!--pending) done(null, results);
                    });
                } else {
                    results.push(file);
                    if (!--pending) done(null, results);
                }
            });
        });
    });
};

getFolderInfo('/home/username', function (err, results) {
    if (err) throw err;
    console.log(results);
});

答案 2 :(得分:0)

如果您不尝试将文件夹层次结构简化为列表,则可以简化此操作。我对您期望如何使用countertotal_size作了一些假设。我也忽略了未使用的depth参数。

const fs = require('fs');
const path = require('path');

async function recurseFolders(folderPath) {
    const fileNames = await fs.promises.readdir(folderPath);
    const fileData = await Promise.all(
        fileNames.map(async (fileName) => {
            const filePath = path.join(folderPath, fileName);
            const fileStat = await fs.promises.stat(filePath);
            if (fileStat.isDirectory()) {
                return recurseFolders(filePath);
            }
            return { 
                name: fileName, 
                path: filePath,
                size: fileStat.size,
                isFolder: false
            };
        })
    );
    const folder = {
        name: path.basename(folderPath),
        path: folderPath,
        files: fileData,
        isFolder: true,
        count: fileData.length,
        size: 0
    };
    return fileData.reduce((total, file) => {
        total.size += file.size;
        if (file.isFolder) {
            total.count += file.count;
        }
        return total;
    }, folder);
}

recurseFolders('some/path/to/folder').then((file) => {
    console.log(file);
}).catch((err) => {
    process.exitCode = 1;
    console.error(err);
});

此实现将返回如下所示的数据结构:

{
    "name": "demo",
    "path": "example/path/demo",
    "files": [
        {
            "name": "dir1",
            "path": "example/path/demo/dir1",
            "files": [
                {
                    "name": "dir2",
                    "path": "example/path/demo/dir1/dir2",
                    "files": [
                        {
                            "name": "file3.txt",
                            "path": "example/path/demo/dir1/dir2/file3.txt",
                            "size": 7412,
                            "isFolder": false
                        }
                    ],
                    "isFolder": true,
                    "count": 1,
                    "size": 7412
                },
                {
                    "name": "file2.txt",
                    "path": "example/path/demo/dir1/file2.txt",
                    "size": 8364,
                    "isFolder": false
                }
            ],
            "isFolder": true,
            "count": 3,
            "size": 15776
        },
        {
            "name": "file1.txt",
            "path": "example/path/demo/file1.txt",
            "size": 6870,
            "isFolder": false
        }
    ],
    "isFolder": true,
    "count": 5,
    "size": 22646
}