node.js的延迟评估/流/ FRP代码fs.readdir异步递归目录搜索

时间:2013-07-12 03:43:04

标签: functional-programming lazy-evaluation reactive-programming lazy-sequences rxjs

我尝试使用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 recursive directory search 是一个很好的参考。

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

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



substack/stream-handbook介绍了如何编写node.js的基础知识 程序streams。 真正优秀的文章。


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

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

  • 搜索结果相当于列表结构,其中功能编程范例很重要(Lisp / Scheme)。

  • 对于JavaScript函数式编程,有一些库,例如 underscore.js ,最近有 lazy.js ,但有一个重要区别:懒惰评估(也称为延迟执行)似乎胜过underscore.js

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

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

  • async 此主题的方法 FRP 主题。

  • 因此,延迟评估是更快的List处理功能编程的核心因素,并将列表扩展为无限列表(流),它将async /事件集成到Stream数据源以进行处理编程范例(FunctionalReactiveProgramming)。

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


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

是否有任何示例代码仅以延迟评估或FRP方式实现此主题?

我知道lazy.js,stream.js或linq.js基于延迟评估,但是其中任何一个都不能将node.js fs.readdir定义为异步处理(FRP)的流数据< / strong>即可。根据{{​​3}},它还没有实现,对吗?

http://danieltao.com/lazy.js/docs/AsyncSequence.html可能可以,但我不知道如何。

RxJS

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

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

的开始

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

(CoffeeScript的)

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