用promises评估递归树路径的顺序

时间:2018-05-18 18:49:06

标签: node.js promise async-await

声称此代码首先使用目录进行处理,然后以递归方式使用子目录。但是命令不是directoryA directoryA / subdirectoryC目录B .A和B是根目录的子代

 const {join} = require('path');
 const {promisify} = require('util');
 const fs = require('fs');
 const readdir = promisify(fs.readdir);
 const stat = promisify(fs.stat);
 async function $readDir (dir, acc = []) {
 await Promise.all((await readdir(dir)).map(async file => {
      file = join(dir, file);
      return (await stat(file)).isDirectory() && acc.push(file) && 
      $readDir(file, acc);
      }));
 return acc;
 }

命令似乎是root:/ dirA root:/ dirb root:/ dirA / dirC 在承诺树中,内在的人首先得到满满的 最后的订单是什么?

2 个答案:

答案 0 :(得分:0)

您正在寻找的算法称为BFS或“广度优先搜索”。它不仅适用于目录,还适用于一般graph traversal

并不是说这通常不是递归算法。

我们的想法是在一个回合中访问每个级别,并将您从下一级别找到的所有内容推送到队列中,然后处理该队列:

const { join } = require('path');
const fs = require('fs').promises;
async function readdirRecursive (dir, acc = []) {
  var queue = [dir];
  while(queue.length > 0) {
    var next = queue.shift();
    // this code does this sequentially and not concurrently
    // if you want to make multiple fs calls then you can by storing
    // levels and doing the call once - per - level, but you already had
    // that

    if (!(await fs.stat(file)).isDirectory()) {
      return; // file, return
    }

    // put code that does something with dir here

    const files = await fs.readdir(next);
    // add all the new candidates
    queue.push(...files.map(f => path.join(next, f)); 
  }
}

答案 1 :(得分:0)

映射到子目录数组的所有函数调用同时运行,如果只是推送到累加器数组,则根本没有保证顺序。

要解决此问题,请按顺序遍历目录:

async function readDirRecursive(dir, acc = []) {
    for (const file of await readdir(dir)) {
        const path = join(dir, file);
        if ((await stat(path)).isDirectory()) {
            acc.push(path);
            await readDirRecursive(path, acc);
        }
    }
    return acc;
}

或者只是不使用共享累加器,但按照您想要的顺序正确连接并发遍历的结果:

async function readDirRecursive(dir) {
    const paths = await Promise.all((await readdir(dir)).map(async file => {
        const path = join(dir, file);
        if ((await stat(path)).isDirectory())
            return [path, ...await readDirRecursive(path, acc)];
        else
            return [];
    });
    return [].concat(...paths);
}
相关问题