Jak*_*zak 3 javascript node.js rxjs
我正在尝试使用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)
})
Run Code Online (Sandbox Code Playgroud)
问题:
.map使用异步操作的更有效/简洁的方法?.zip部分好问题。
我认为您可以做一些事情来优化此查询。
首先,我们可以改变mapopeartors随后.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}`)
})
Run Code Online (Sandbox Code Playgroud)
我认为主要的改进是您实际上两次访问了文件系统。在filesInDir观察到的序列不是热/缓存序列。如果是这样,则目录树的递归遍历将不起作用。考虑到这一点,您一次调用它来获取所有文件,然后再次调用它来进行isDirectory检查。这既引入了潜在的性能成本,又引入了错误。您假设当您打磁盘时,返回的文件序列将始终是相同的顺序。即使我们忽略了一秒钟,该磁盘也是可变的,并且它可能在你之下改变。您可以保证,在异步世界中,序列将以相同顺序返回。在我的机器上(Windows 10),该序列通常以相同顺序返回。但是,如果有足够深的树(例如,来自_C:_的树),我每次都会遇到不匹配的情况。
无论如何,性能修复还是错误修复。不必每次都从文件系统中重新读取,我们可以这样做一次。将statFile()调用移至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}`)
})
}
Run Code Online (Sandbox Code Playgroud)
这也具有删除Zip子句的好处,因为我们不再尝试使用两个序列。
| 归档时间: |
|
| 查看次数: |
1039 次 |
| 最近记录: |