我本身对node的api并不熟悉,多的是学习别人的代码。 一个深度获取目录的函数,是在同行的代码的借鉴过来的,也一直在用。
read_all_files = (path) => {
var pa = fs.readdirSync(path);
var files = [];
pa.forEach((ele, index) => {
let child = path + "/" + ele;
let info = fs.statSync(child);
if (info.isDirectory()) {
let subs = read_all_files(child);
subs.forEach((s) => files.push(s));
} else {
files.push(child);
}
});
return files;
};
在学习的过程中,我也尝试重写他的代码,改成了下面这样的。但基本上变化不大。只是增加了入参的包容程度。
import { readdirSync, statSync, Stats } from "fs";
/** 迭代返回子级文件
* @param path 读取目录
* @returns 全部子文件清单
*/
export function read_all_files(path: string | ReadonlyArray<string>): string[] {
/** 文件集处理 */
let active: (fileStats: Stats) => ((context: string[], newfile: string) => number)
= a => a.isDirectory()
? (b, c) => b.push.apply(b, read_all_files(c))
: (b, c) => b.push(c);
let files: string[] = [];
if (typeof(path)=='string')
readdirSync(path)
.map(e => path + '/' + e)
.forEach(child => active(statSync(child))(files, child));
else
files = path.map(read_all_files).flat()
return files;
};
昨天在看一个老外的代码的时候,学到fs.readdirSync可以带参,加上这两年的开发经验,就尝试重做了这个深度遍历。
/** 深度获取目录 */
export function DeepRead(path: string | ReadonlyArray<string>): string[] {
return [path]
.flat()
.map(dir =>
readdirSync(dir, { withFileTypes: true })
.map(e => {
if (e.isDirectory())
return DeepRead(`${dir}/${e.name}`)
return `${dir}/${e.name}`
})
)
.flat(2)
}
我对一个 有将近5000个文件的目录进行了测试,测试结果也确实令我大吃一惊。居然有十倍的差距。
console.time('read_all_file')
read_all_file('maps')
console.timeEnd('read_all_file')
console.time('read_all_files')
read_all_files('maps')
console.timeEnd('read_all_files')
console.time('DeepRead')
DeepRead('maps')
console.timeEnd('DeepRead')
// read_all_file: 130.862ms
// read_all_files: 118.388ms
// DeepRead: 12.851ms
也有一些小测试
对于可能是数组也可能是字符串的参数,Array.isArray(path) ? path : [path]也不会比[path].flat()存在优势。
Array.flatMap也不是完全比Array.map().flat()存在优势,甚至可能会更慢。