gpt4 book ai didi

javascript - 使用 RxJs 在 node.js 中遍历目录树

转载 作者:搜寻专家 更新时间:2023-10-31 23:34:56 24 4
gpt4 key购买 nike

我正在尝试使用 RxJs 和 node.js 遍历目录树。

我想出了可行的解决方案:

const filesInDir = Rx.Observable.fromNodeCallback(fs.readdir)
const statFile = Rx.Observable.fromNodeCallback(fs.stat)

const listFiles = (prefix, dir = '') => {
const file$ = filesInDir(`${prefix}/${dir}`)
.flatMap(file => file)
.filter(file => !file.startsWith('.'))
const isDir$ = file$
.map(file => statFile(`${prefix}/${dir}/${file}`))
.flatMap(file => file)
.map(file => file.isDirectory())
return file$
.zip(isDir$, (file, isDir) => {return {file, isDir}})
.map(f => {
if (f.isDir) {
return listFiles(prefix, `${dir}/${f.file}`)
}
return Rx.Observable.return(`${dir}/${f.file}`)
})
.flatMap(file => file)
}

listFiles('public')
.toArray()
.subscribe(list => {
console.log(list)
})

问题:

  1. .map 使用异步操作是否有更高效/简洁的方法?
  2. .zip 部分的相同问题

最佳答案

好问题。

我认为您可以做一些事情来优化这个查询。

首先,我们可以将 map opeartors 后跟 .flatMap(file => file) 更改为单个 flatMap。微小的改进,但会运行更少的代码。

const file$ = filesInDir(`${prefix}/${dir}`)
.flatMap(file => file)
.filter(file => !file.startsWith('.'))
const isDir$ = file$
.flatMap(file => statFile(`${prefix}/${dir}/${file}`))
.map(file => file.isDirectory())
return file$
.zip(isDir$, (file, isDir) => {return {file, isDir}})
.flatMap(f => {
if (f.isDir) {
return listFiles(prefix, `${dir}/${f.file}`)
}
return Rx.Observable.return(`${dir}/${f.file}`)
})

主要改进是我相信您实际上两次访问了文件系统。filesInDir 可观察序列不是热/缓存序列。如果是这样,目录树的递归遍历将不起作用。考虑到这一点,您调用它一次以获取所有文件,然后您再次调用它以执行 isDirectory 检查。这引入了潜在的性能成本和错误。您假设当您访问磁盘时,返回的文件序列将始终以相同的顺序排列。即使我们忽略一秒钟,该磁盘也是可变的,并且它可能在您的控制下发生变化。您可以保证在异步世界中,序列将以相同的顺序返回。在我的机器(Windows 10)上,序列大部分以相同的顺序返回。然而,如果树足够深(例如来自 _C:_),我每次都会遇到不匹配。

无论如何,性能修复也是错误修复。我们可以做一次,而不是每次都从文件系统中重新读取。将 statFile() 调用移动到 flatMap 中,该 flatMap 也将结果与传递给 statFile

的文件的闭包进行映射
const listFiles = (prefix, dir) => {
return file$ = filesInDir(`${prefix}/${dir}`)
.flatMap(file => file)
.filter(file => !file.startsWith('.'))
.flatMap(file => statFile(`${prefix}/${dir}/${file}`)
.map( sf => {return {file, isDir: sf.isDirectory()}}) )
.flatMap(f => {
if (f.isDir) {
return listFiles(prefix, `${dir}/${f.file}`)
}
return Rx.Observable.return(`${dir}/${f.file}`)
})
}

这也有删除 Zip 子句的好处,因为我们不再尝试使用两个序列。

关于javascript - 使用 RxJs 在 node.js 中遍历目录树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36366962/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com