重构代码,承诺读取文件并将其转换为 json

Refactor code with promises to read files and convert them to json

我正在尝试执行以下操作:读取目录的内容以查找所有 .xml 文件(我为此目的使用 glob but I'd like to use something like fs.readdir from fs), then I want to read every file using fs.readFile and then I want to convert the xml file to JSON objects. I'm using 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()

但是,我想转向更简洁优雅的解决方案(使用 promises)。我一直在阅读社区,并在一些类似的帖子中找到了一些想法 or here

对于这种情况我应该如何处理,我想听听您的意见。我应该改用 readFile 的同步版本吗?我应该使用 promisifyAll 来重构我的代码并在任何地方使用 promises 吗?如果是这样,您能否详细说明我的代码应该是什么样子?

我还了解到有一个promises based version of fs from node v10.0.0 onwards. Should I go for that option? If so how should I proceed with the parser.toJson() part. I've also seen that there's another promise-based version called xml-to-json-promise

非常感谢您对此的见解,因为当涉及多个异步操作和循环时,我对 promises 不是很熟悉,所以我最终得到了针对这种情况的肮脏解决方案。

此致, J

我确实建议你使用 globfs 的 promise 版本,然后使用 asyncawaitPromise.all 来全部完成。

注意:我没有看到关于 connectors.length === files.length 检查的逻辑,因为理论上连接器(属性)的数量可以大于文件的数量。我假设您想收集 所有 个,而不考虑它们的数量。

下面是代码的样子(未经测试):

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...
});