在这个 Expressjs 路由文件中,我试图(递归)获取 ./ data 目录中的所有JSON文件。
实际上,我可以 console.log 该文件,在这里您可以看到 A Mark ,但是我找不到将完整的路径发送到异步工作完成后,视图就会出现。
我们将不胜感激。
这是数据 ./ data 结构:
--- dir1
`-- json1.json
`-- json2.json
--- dir2
`-- json3.json
--- dir3
const express = require('express'),
router = express.Router(),
fs = require('fs'),
path = require('path')
;
let scan = function (directoryName = './data') {
return new Promise((resolve, reject) => {
fs.readdir(directoryName, function (err, files) {
if (err) reject(err);
files.map((currentValue, index, arr) => {
let fullPath = path.join(directoryName, currentValue);
fs.stat(fullPath, function (err, stat) {
if (err) reject(err);
if (stat.isDirectory()) {
scan(fullPath);
} else {
console.log(currentValue); <= (A mark)
//resolve();
}
});
});
});
})
};
router.get('/', (req, res, next) => {
scan()
.then(data => res.render('list', {
title: 'List',
data: data
}))
.catch(next);
});
module.exports = router;
答案 0 :(得分:1)
如果您承诺要使用的fs
函数可以简化一堆任务,以便所有异步逻辑都是Promise,然后使用async / await帮助您序列化控制流。
这是一种方法:
const promisify = require('util').promisify;
const path = require('path');
const fs = require('fs');
const readdirp = promisify(fs.readdir);
const statp = promisify(fs.stat);
async function scan(directoryName = './data', results = []) {
let files = await readdirp(directoryName);
for (let f of files) {
let fullPath = path.join(directoryName, f);
let stat = await statp(fullPath);
if (stat.isDirectory()) {
await scan(fullPath, results);
} else {
results.push(fullPath);
}
}
return results;
}
以上代码已在节点v10.14.1中进行了测试。
然后可以使用与以前相同的方式:
router.get('/', (req, res, next) => {
scan().then(data => res.render('list', {
title: 'List',
data: data
})).catch(next);
});
仅供参考,fs
模块有一个更新的(仍处于试验阶段)基于承诺的API。您可以这样使用:
const path = require('path');
const fsp = require('fs').promises;
async function scan2(directoryName = './data', results = []) {
let files = await fsp.readdir(directoryName, {withFileTypes: true});
for (let f of files) {
let fullPath = path.join(directoryName, f.name);
if (f.isDirectory()) {
await scan2(fullPath, results);
} else {
results.push(fullPath);
}
}
return results;
}
请注意,此新版本还使用了新的withFileTypes
选项,省去了在每个文件上调用stat()
的麻烦。
答案 1 :(得分:0)
为此有一个NPM模块:
它允许您以同步或异步方式将目录树表示为字符串或对象。使用文件回调,您也可以实现目标。如果需要,还可以指定要考虑的文件扩展名。
代码如下:
const dree = require('dree');
const path = './myFolder';
const options = {
extensions: [ 'json' ], // Only json files are considered
normalize: true, // If you want all the paths to use only / (slashes) and not \ (backslashes) on windows
followLinks: true // If you want to follow and inspect even symbolic links to other directories
}
// In case you want the absolute paths of the json files
const paths = [];
// In case you want the relative paths of the json files
const relativePaths = [];
const fileCallback = function(fileNode) {
paths.push(fileNode.path);
relativePaths.push(fileNode.relativePath);
}
dree.scanAsync(path, options, fileCallback)
.then(tree => {
// paths contains all the paths you want
// relativePaths the same but the paths are relative
// tree contains an object representing all the folder tree including only json files
});
使用异步并等待:
const dree = require('dree');
const path = './myFolder';
const options = {
extensions: [ 'json' ], // Only json files are considered
normalize: true, // If you want all the paths to use only / (slashes) and not \ (backslashes) on windows
followLinks: true // If you want to follow and inspect even symbolic links to other directories
}
// In case you want the absolute paths of the json files
const paths = [];
// In case you want the relative paths of the json files
const relativePaths = [];
const fileCallback = function(fileNode) {
paths.push(fileNode.path);
relativePaths.push(fileNode.relativePath);
}
async function execute() {
const tree = await dree.scanAsync(path, options, fileCallback)
// paths contains all the paths you want
// relativePaths the same but the paths are relative
// tree contains an object representing all the folder tree including only json files
}
execute();
答案 2 :(得分:0)
以上所有示例在处理找到的条目之前都会创建一个大结果数组。
这是一种将给定目录和子目录的所有找到的文件条目“流式传输”到迭代器中的解决方案。
现在可以将过滤器添加到流中,以将结果减少到过滤器规则中。 在此示例中,仅接受markdown文件。
const fsp = require('fs').promises;
const path = require('path');
// scan the directory recursively and push each filename into the iterator.
async function* scan3(dir) {
const entries = await fsp.readdir(dir, { withFileTypes: true });
for (const de of entries) {
const res = path.resolve(dir, de.name);
// console.log('>' + res);
if (de.isDirectory()) {
yield* scan3(res);
} else {
yield res;
}
}
}
// get all filenames from the iterator param
// and push each filename with valid extension into the resulting iterator.
async function* filterExt(it, ext) {
for await (const e of it) {
if (e.endsWith(ext)) {
// console.log('>>' + e);
yield e;
}
}
}
async function main() {
const it_files = scan3('.')
const it_mdFiles = filterExt(it_files, '.md');
for await (const f of it_mdFiles) {
console.log('>>>' + f);
}
}
main();
console.log("done.");
只需启用console.log行即可查看在哪个阶段处理了什么文件名。