递归读取目录并在NodeJS中创建对象
我一直在努力尝试自动化并清理如何在我的HTML5游戏中使用精灵生成和加载,使用NodeJS socket.io服务器发送包含生成精灵所需数据的对象。
我想要做的是阅读目录/img
及其所有子目录(/assets1
,/assets2
,/assets3
等),并根据它们的数据和结构创建一个对象。我遇到的问题是我找不到一个很好的方法来处理/assets3
的子目录。以下是我的资产设置示例:
这里是我想要实现的对象示例但是没有使用无穷无尽的if
/ else
s,这对我来说似乎并不吸引人,并且必须有更好的方法来使用库。
var outputWeWant = {
assets1: {
img1: '/img/assets1/img1.png',
img2: '/img/assets1/img2.png',
},
assets2: {
img1: '/img/assets2/img1.png',
img2: '/img/assets2/img2.png',
},
assets3: {
img1: '/img/assets3/img1.png',
img2: '/img/assets3/img2.png',
assets4: {
img1: '/img/assets3/assets4/img1.png'
}
}
}
下面只是我做过的一点头脑风暴,但这并不像我想要的那样有效,看起来很恶心,所有的都是目录检查,因为我们在assets4中添加了一个新目录
fs.readdirSync('/img/').map(dirName => {
fs.readdirSync('/img/' + dirName).map(fileName => {
if (fs.statSync('/img/' + dirName + '/' + fileName).isDirectory()) {
// Read the new directory and add the files to our object
} else {
// It's not a directory, just add it to our object
}
});
});
回答如下:
这种潜在的无限操作需要recursive function。我将假设这个函数是为Node编写的,我将把文件系统细节留给OP。此代码段应视为伪代码。
function parseDirectory(directory) {
return directory.getItems().reduce((out, item) => {
switch (item.type) {
case 'file':
out[item.name] = item.path;
break;
case 'directory':
out[item.name] = parseDirectory(item.path);
break;
}
return out;
}, {});
}
通过OP中添加的fs
代码,这是一个(理论上)工作函数:
function parseDirectory(directory) {
return fs.readdirSync(directory).reduce((out, item) => {
const itemPath = `${directory}/${item}`;
if (fs.statSync(itemPath).isDirectory()) {
out[item] = parseDirectory(itemPath);
} else {
out[item] = itemPath;
}
return out;
}, {});
}
如果reduce()
的语法太习惯你的喜好,试试这个:
function parseDirectory(directory) {
let out = {};
fs.readdirSync(directory).forEach(item => {
const itemPath = `${directory}/${item}`;
if (fs.statSync(itemPath).isDirectory()) {
out[item] = parseDirectory(itemPath);
} else {
out[item] = itemPath;
}
});
return out;
}
递归读取目录并在NodeJS中创建对象
我一直在努力尝试自动化并清理如何在我的HTML5游戏中使用精灵生成和加载,使用NodeJS socket.io服务器发送包含生成精灵所需数据的对象。
我想要做的是阅读目录/img
及其所有子目录(/assets1
,/assets2
,/assets3
等),并根据它们的数据和结构创建一个对象。我遇到的问题是我找不到一个很好的方法来处理/assets3
的子目录。以下是我的资产设置示例:
这里是我想要实现的对象示例但是没有使用无穷无尽的if
/ else
s,这对我来说似乎并不吸引人,并且必须有更好的方法来使用库。
var outputWeWant = {
assets1: {
img1: '/img/assets1/img1.png',
img2: '/img/assets1/img2.png',
},
assets2: {
img1: '/img/assets2/img1.png',
img2: '/img/assets2/img2.png',
},
assets3: {
img1: '/img/assets3/img1.png',
img2: '/img/assets3/img2.png',
assets4: {
img1: '/img/assets3/assets4/img1.png'
}
}
}
下面只是我做过的一点头脑风暴,但这并不像我想要的那样有效,看起来很恶心,所有的都是目录检查,因为我们在assets4中添加了一个新目录
fs.readdirSync('/img/').map(dirName => {
fs.readdirSync('/img/' + dirName).map(fileName => {
if (fs.statSync('/img/' + dirName + '/' + fileName).isDirectory()) {
// Read the new directory and add the files to our object
} else {
// It's not a directory, just add it to our object
}
});
});
回答如下:
这种潜在的无限操作需要recursive function。我将假设这个函数是为Node编写的,我将把文件系统细节留给OP。此代码段应视为伪代码。
function parseDirectory(directory) {
return directory.getItems().reduce((out, item) => {
switch (item.type) {
case 'file':
out[item.name] = item.path;
break;
case 'directory':
out[item.name] = parseDirectory(item.path);
break;
}
return out;
}, {});
}
通过OP中添加的fs
代码,这是一个(理论上)工作函数:
function parseDirectory(directory) {
return fs.readdirSync(directory).reduce((out, item) => {
const itemPath = `${directory}/${item}`;
if (fs.statSync(itemPath).isDirectory()) {
out[item] = parseDirectory(itemPath);
} else {
out[item] = itemPath;
}
return out;
}, {});
}
如果reduce()
的语法太习惯你的喜好,试试这个:
function parseDirectory(directory) {
let out = {};
fs.readdirSync(directory).forEach(item => {
const itemPath = `${directory}/${item}`;
if (fs.statSync(itemPath).isDirectory()) {
out[item] = parseDirectory(itemPath);
} else {
out[item] = itemPath;
}
});
return out;
}