带有承诺的代码以读取文件并将其转换为json

问题描述 投票:0回答:1

[我正在尝试执行以下操作:阅读目录的内容以查找所有.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()

但是,我想转到一个更干净,更优雅的解决方案(使用诺言)。我正在阅读社区,并且在一些类似的帖子herehere中发现了一些想法。

我希望您对在这种情况下应如何处理保持看法。我应该改为使用readFile的同步版本吗?我是否应该使用promisifyAll重构代码并在任何地方使用Promise?如果是这样,请您详细说明一下我的代码是什么样的?

我还了解到,从节点v10.0.0开始有一个promises based version of fs。我应该选择那个吗?如果是这样,我应该如何进行parser.toJson()部分。我也看到了另一个基于承诺的版本xml-to-json-promise

非常感谢您对此的见解,因为当涉及多个异步操作和循环时,我对Promise不太熟悉,因此我最终遇到了类似这种情况的肮脏解决方案。

关于,J

node.js asynchronous promise fs bluebird
1个回答
1
投票

我确实建议您使用globfs的Promise版本,然后使用asyncawaitPromise.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... });

© www.soinside.com 2019 - 2024. All rights reserved.