node.js fs.readdr异步递归目录搜索的懒惰评估/Stream/FRP代码



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

DIR/文件结构:

DIR1
     DIR2R
     file1
     file2
     file3
     …

->列表结构:

("DIR1" ("DIR2" "file1" "file2" "file3" …))
 DIR()   //looks like a C function
 file    //looks like an Atom value

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

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手册介绍了如何编写node.js的基本知识带有流的程序。真正优秀的文章


因此,以下是我对这个主题的思考-递归目录树处理:

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

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

  • 对于JavaScript函数式编程,有一些库,如underline.js和最近的lazy.js惰评估(也称为延迟执行),其中似乎优于underline.js

  • lazy.js也将流处理封装在Node.js中。我还发现stream.js说:有无限多的元素。它们的力量来自于懒惰的评估,简单地说,这意味着它们可以包含无限的项目

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

  • async这个主题的方法一个FRP主题。

  • 因此,懒惰评估是更快列表处理功能编程的核心因素,它将列表扩展到无限列表(流),该列表将异步/事件集成到流数据源,以在功能编程范式(FunctionalReactiveProgramming)中进行处理。

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


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

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

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

RxJS可能可以,但我不知道怎么做。

谷歌rx.ObsObservable fs.readdir什么都不点击。

有什么想法吗?

以下是基于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

最新更新