[我正在尝试执行以下操作:阅读目录的内容以查找所有.xml文件(我正在使用glob,但我想使用fs中的fs.readdir之类的东西),然后我我想使用fs.readFile读取每个文件,然后将xml文件转换为JSON对象。我为此使用xml2json。
[一旦有了json对象,我想迭代它们中的每个对象,以从中获取一个属性并将其推入数组。最终,所有代码都包装在记录数组内容的函数中(一旦完成)。该代码目前可以正常工作,但我正进入著名的回调地狱。
const fs = require('fs');
const glob = require('glob');
const parser = require('xml2json');
let connectors = []
function getNames(){
glob(__dirname + '/configs/*.xml', {}, (err, files) => {
for (let j=0; j < files.length; j++) {
fs.readFile( files[j], function(err, data) {
try {
let json = parser.toJson(data, {object: true, alternateTextNode:true, sanitize:true})
for (let i=0; i< json.properties.length; i++){
connectors.push(json.properties[i].name)
if (connectors.length === files.length){return console.log(connectors)}
}
}
catch(e){
console.log(e)
}
});
}
})
}
getNames()
但是,我想转到一个更干净,更优雅的解决方案(使用诺言)。我正在阅读社区,并且在一些类似的帖子here或here中发现了一些想法。
我希望您对在这种情况下应如何处理保持看法。我应该改为使用readFile的同步版本吗?我是否应该使用promisifyAll重构代码并在任何地方使用Promise?如果是这样,请您详细说明一下我的代码是什么样的?
我还了解到,从节点v10.0.0开始有一个promises based version of fs。我应该选择那个吗?如果是这样,我应该如何进行parser.toJson()部分。我也看到了另一个基于承诺的版本xml-to-json-promise。
非常感谢您对此的见解,因为当涉及多个异步操作和循环时,我对Promise不太熟悉,因此我最终遇到了类似这种情况的肮脏解决方案。
关于,J
我确实建议您使用glob
和fs
的Promise版本,然后使用async
,await
和Promise.all
完成所有操作。
NB:我看不到有关connectors.length === files.length
检查的逻辑,因为从理论上讲,连接器(属性)的数量可以大于文件的数量。我假设您要收集其中的[[all,无论其数量如何。
const fs = require('fs').promises; // Promise-version (node 10+)
const glob = require('glob-promise'); // Promise-version
const parser = require('xml2json');
async function getNames() {
let files = await glob(__dirname + '/configs/*.xml');
let promises = files.map(fileName => fs.readFile(fileName).then(data =>
parser.toJson(data, {object: true, alternateTextNode:true, sanitize:true})
.properties.map(prop => prop.name)
));
return (await Promise.all(promises)).flat();
}
getNames().then(connectors => {
// rest of your processing that needs access to connectors...
});
正如在注释中所写,您在访问properties.map
时遇到问题,执行一些验证,并跳过没有properties
的情况:
const fs = require('fs').promises; // Promise-version (node 10+) const glob = require('glob-promise'); // Promise-version const parser = require('xml2json'); async function getNames() { let files = await glob(__dirname + '/configs/*.xml'); let promises = files.map(fileName => fs.readFile(fileName).then(data => (parser.toJson(data, {object: true, alternateTextNode:true, sanitize:true}) .properties || []).map(prop => prop.name) )); return (await Promise.all(promises)).flat(); } getNames().then(connectors => { // rest of your processing that needs access to connectors... });