порядок оценки пути рекурсивного дерева с обещаниями - PullRequest
0 голосов
/ 18 мая 2018

Этот код, как утверждается, сначала обрабатывается с каталогами, а затем рекурсивно с подкаталогами. Но порядок не будет каталогом 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 голосов
/ 19 мая 2018

Все вызовы функций, которые отображаются в вашем массиве подкаталогов, выполняются одновременно, и если вы просто нажмете на свой массив-накопитель, то вообще не будет гарантированного порядка.

Чтобы исправить это, либо проследуйте по каталогам последовательно:

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);
}
0 голосов
/ 19 мая 2018

Алгоритм, который вы ищете, называется BFS или «поиск в ширину».Это относится не только к каталогам, но и к общему обходу графа .

Не то чтобы это, как правило, не рекурсивный алгоритм.

Идея состоит в том, чтобы посещать каждый уровень по очереди и помещать все найденное на следующем уровне в очередь, а затем обрабатывать эту очередь:

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