【问题标题】:I have a functional way to read a directory and log the stats, how I can get all folders tree stats recursively in a functional way?我有一种读取目录和记录统计信息的功能性方式,如何以功能性方式递归获取所有文件夹树统计信息?
【发布时间】:2020-12-04 13:38:08
【问题描述】:

我能够制作下面的代码,它只读取一个目录,然后记录一个 Stats 列表。 现在我想知道如何遍历目录树并检索具有统计信息和文件路径的对象列表。

import fs from 'fs'
import {Task, traverse,concat,compose,chain,map, prop, List, filter } from './shared/functional.js';

// readDir :: String -> Task Error (List String)
const readDir = path => new Task((reject, result) => {
  fs.readdir(path, (err, data) => (err ? reject(err) : result(new List(data))));
});

// readDir :: String -> Task Error (Stat)
const readStat = filename => new Task((reject, result) => {
  fs.stat(filename, (err, data) => (err ? reject(err) : result(data)));
});

const dirList = dir => chain(traverse(Task.of, compose(readStat, concat(dir))), readDir(dir),);

dirList('./shared/').fork(console.error, map(compose(console.log, prop('mtimeMs'))));

我猜我需要使用 isDirectory 来检查我是否应该进入树的内部。但我的问题是如何构造对象以及如何返回非嵌套列表?

编辑:我现在没有使用任何库,只是遵循 https://mostly-adequate.gitbooks.io/mostly-adequate-guide/ 的类型和助手

EDIT2:我想出了以下内容:

import fs from 'fs'
import {Task, traverse,concat,compose,chain,map, prop, List, filter, Maybe,identity,Either,curry } from './shared/functional.js';

// readDir :: String -> Task Error (List String)
const readDir = path => new Task((reject, result) => {
  fs.readdir(path, (err, data) => (err ? reject(err) : result(new List(data))));
});

// readDir :: String -> Task Error (Stat)
const readStat = filename => new Task((reject, result) => {
  fs.stat(filename, (err, data) => (err ? reject(err) : result(data)));
});

const isDir = curry((dir, stat) => {
  return stat.isDirectory()
    // eslint-disable-next-line no-use-before-define
    ? dirListAll(dir)
    : stat;
});

const dirListAll = dir => chain(traverse(Task.of, compose(map(isDir(dir)),readStat, concat(dir))), readDir(dir),);

现在我有了我解释的场景,在这个示例中,我有一个目录,其中包含 6 个项目,即 2 个文件夹。所以我得到了一个包含 4 个统计数据和 2 个任务的列表。

Task {fork: ƒ} 0 (6) [Task, Stats, Stats, Stats, Task, Stats]

后面可以包含列表,我现在需要的是删除外部函子,我正在尝试可能再次使用遍历链。但还没有成功。 再次感谢。

【问题讨论】:

    标签: javascript node.js functional-programming


    【解决方案1】:

    您可能已经注意到回调和循环不能很好地结合在一起。为了解决这个问题,我推荐使用util.promisify。完成后,您可以轻松编写如下异步函数:

    async function traverse(names, callback) {
      for (let name of names) {
        let s = await stat(name);
        if (s.isDirectory())
          await traverse( (await readdir(name)).map(x => path.join(name, x)) , callback );
        else
          callback(name);
      }
    }
    

    【讨论】:

    • 嗨,我已经有一个异步代码(与互联网上的许多其他代码一样),它使用 Promises 来实现,但它们并不纯。它必须是功能性的。我需要能够在不实际触发它们的情况下编写调用。就像上面代码中的 Task 一样。任务类型的工作方式与 Promise 类似,但具有功能性。所以这不是我要找的。我会更新编辑标题谢谢。
    • @Ricardo 我想你可以创建一个异步包装函数并使用它而不是 promisify?
    • 这就是Task正在做的事情。问题是我已经拥有了如何在没有列表中的任务的情况下获取树统计信息的功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-26
    相关资源
    最近更新 更多