我有一个来自readdirp模块的目录流。
我想:-
README.*)搜索文件#开头的文件的第一行我正在尝试使用streams和highland.js来完成这个任务。
我无法处理每个目录中所有文件的流。
h = require 'highland'
dirStream = readdirp root: root, depth: 0, entryType: 'directories'
dirStream = h(dirStream)
.filter (entry) -> entry.stat.isDirectory()
.map (entry) ->
# Search all files in the directory for README.
fileStream = readdirp root: entry.fullPath, depth: 0, entryType: 'files', fileFilter: '!.DS_Store'
fileStream = h(fileStream).filter (entry) -> /README\..*/.test entry.name
fileStream.each (file) ->
readmeStream = fs.createReadStream file
_(readmeStream)
.split()
.takeUntil (line) -> not line.startsWith '#' and line isnt ''
.last(1)
.toArray (comment) ->
# TODO: How do I access `comment` asynchronously to include in the return value of the map?
return {name: entry.name, comment: comment}发布于 2015-07-09 10:35:36
最好将高地流视为不可变的,并且像filter和map这样的操作返回依赖于旧流的新流,而不是对旧流的修改。
另外,Highland方法很懒:只有在绝对需要数据时才应该调用each或toArray。
异步映射流的标准方法是flatMap。它类似于map,但是您给它的函数应该返回一个流。从flatMap获得的流是所有返回流的连接。由于新流按顺序依赖于所有旧流,因此可以用来对异步进程进行排序。
我将您的示例修改为以下内容(澄清了一些变量名称):
h = require 'highland'
readmeStream = h(readdirp root: root, depth: 0, entryType: 'directories')
.filter (dir) -> dir.stat.isDirectory()
.flatMap (dir) ->
# Search all files in the directory for README.
h(readdirp root: dir.fullPath, depth: 0, entryType: 'files', fileFilter: '!.DS_Store')
.filter (file) -> /README\..*/.test file.name
.flatMap (file) ->
h(fs.createReadStream file.name)
.split()
.takeUntil (line) -> not line.startsWith '#' and line isnt ''
.last(1)
.map (comment) -> {name: file.name, comment}让我们看看这段代码中的类型。首先,注意flatMap有类型(以Haskellish符号表示) Stream a → (a → Stream b) → Stream b,即它接受一个包含一些a类型的东西的流,以及一个期望a类型的事物和包含bs的返回流的函数,并返回一个包含b的流。集合类型(例如流和数组)实现flatMap作为连接返回的集合的标准。
h(readdirp root: root, depth: 0, entryType: 'directories')假设这里有Stream Directory类型。filter不会更改类型,所以flatMap将是Stream Directory → (Directory → Stream b) → Stream b。我们将看到函数返回的内容:
h(readdirp root: dir.fullPath, depth: 0, entryType: 'files', fileFilter: '!.DS_Store')把这称为Stream File,所以第二个flatMap是Stream File → (File → Stream b) → Stream b。
h(fs.createReadStream file.name)这是一个Stream String。split、takeUntil和last不会改变这一点,那么map是做什么的呢?map非常类似于flatMap:它的类型是Stream a → (a → b) → Stream b。在本例中,a是String,b是对象类型{name : String, comment : String}。然后map返回该对象的流,这就是整个flatMap函数返回的内容。上一步,第二个b中的flatMap是对象,所以第一个flatMap的函数也返回对象的流,所以整个流是一个Stream {name : String, comment : String}。
请注意,由于Highland的懒惰,这实际上不会启动任何流或处理。您需要使用each或toArray来导致thunk并启动管道。在each中,回调将与对象一起调用。取决于您想要对这些注释做些什么,最好再使用一些flatMap (例如,如果您将它们写到一个文件中)。
我不是有意写文章的。希望这能有所帮助。
https://stackoverflow.com/questions/27721268
复制相似问题