2

我尝试使用 node.js 实现一个读取 FileSystem 目录树的列表结构

目录/文件结构:

DIR1
     DIR2R
     file1
     file2
     file3
     …

-> 列表结构:

("DIR1" ("DIR2" "file1" "file2" "file3" …))

 DIR()   //looks like a C function
 file    //looks like an Atom value

因此,例如,给定的 UNIX 根目录:

root bin  cd
          ls

     lib  file1
          file2

     opt

     usr  file3

     file4

相当于一个列表:

("root" ("bin" ("cd" "ls")
         "lib" ("file1" "file2") 
         "opt" ()
         "usr" ("file3")
         "file4"
        )
)

话虽如此,我想用一些惰性异步序列(流/无限列表?)来实现这段代码。

node.js fs.readdir 递归目录搜索 是一个很好的参考。

node.js 有很多优秀的库,例如file.walk等,但这是一个非常有趣的主题,实际上存在很多代码示例。

换句话说,学习惰性异步序列(流/无限列表?)的基本概念的好主题,并且代码可以是一个很好的库,我想从头开始实现。



substack/stream-handbook涵盖了如何使用编写 node.js 程序的基础知识。真正优秀的文章。


所以,这是我对这个主题的想法 - 递归目录树处理:

  • 本主题涉及递归搜索,有两种方式:asyncsync,由于各种原因,我选择了async方法。

  • 搜索结果相当于一个列表结构,其中函数式编程 范式确实很重要(Lisp/Scheme)。

  • 对于 JavaScript 函数式编程,有诸如underscore.js之类的库,最近,lazy.js有一个重要区别:惰性求值(也称为延迟执行)似乎优于 underscore.js

  • lazy.js 也在 Node.js 中封装了流处理。我还发现stream.js说:无限数量的元素。他们的力量来自于被懒惰的评估,简单来说就是他们可以包含无限的物品。.

  • 流数据(无限列表)实现反应式函数式编程(FRP)范式。lazy.js 实际上演示了一个鼠标事件 FRP 实现。RxJS是一个 FRP 库:RxJS 或 Reactive Extensions for JavaScript 是一个用于转换、组合和查询数据流的库。

  • 此主题的异步方法FRP主题。

  • 因此,惰性求值是函数式编程更快处理列表的核心因素,并将列表扩展为无限列表(流),将异步/事件集成到流数据源以在函数式编程范式(FunctionalReactiveProgramming)中进行处理。

  • node-lazy简介明确指出:当您需要将事件流视为列表时,Lazy 非常方便。目前最好的用例是从异步函数返回一个惰性列表,并通过事件将数据泵入其中。在异步编程中,您不能只返回一个常规列表,因为您还没有数据。到目前为止,通常的解决方案是提供一个在数据可用时调用的回调。但是这样做会失去链接函数和创建管道的能力,这会导致接口不那么好。(请参阅下面的第二个示例,了解它如何改进我的一个模块中的界面。)


最后,这是我关于这个主题的问题 - 递归目录树处理:

是否有任何示例代码可以专门以惰性评估或 FRP 方式实现此主题?

我知道lazy.js、stream.js 或linq.js 是基于惰性评估的,但它们中的任何一个都不能将node.js fs.readdir 定义为异步处理(FRP)的流数据。根据http://danieltao.com/lazy.js/docs/AsyncSequence.html,它还没有实现,对吗?

RxJS可能可以,但我不知道如何。

谷歌rx.Observable fs.readdir什么也没打。

有任何想法吗?

4

1 回答 1

0

这是基于https://gist.github.com/edygar/ee0945a73c79182367df的开始

给定一个目录,它会生成一个子目录列表。

(咖啡稿)

Rx = require "rx"
fs = require "fs"

readdir = Rx.Observable.fromNodeCallback fs.readdir
stat = Rx.Observable.fromNodeCallback (pathName, cb) ->
    fs.stat pathName, (err, stats) ->
        stats.pathName = pathName
        cb err, stats

dirObservable = (dirPath) ->
    readdir dirPath
        .flatMap (items) -> Rx.Observable.from items
        .flatMap (item) -> stat item
        .filter (stats) -> stats.isDirectory()
        .map (stats) -> stats.pathName

module.exports = dirObservable


if not module.parent
    path = require "path"
    dirobs = dirObservable path.resolve __dirname, ".."
    dirobs.subscribe (data) -> console.log data
于 2015-01-08T17:59:18.593 回答