【发布时间】:2020-06-06 21:16:27
【问题描述】:
我正在尝试执行以下操作:读取目录的内容以查找所有 .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()
但是,我想转向一个更干净、更优雅的解决方案(使用 Promise)。我一直在阅读社区,并在here 或here 的一些类似帖子中找到了一些想法。
我想听听您对我应该如何处理这种情况的意见。我应该改用 readFile 的同步版本吗?我应该使用promisifyAll 重构我的代码并在任何地方使用promise 吗?如果是这样,您能否详细说明我的代码应该是什么样的?
我还了解到从节点 v10.0.0 开始有一个 promises based version of fs。我应该选择那个选项吗?如果是这样,我应该如何处理 parser.toJson() 部分。我还看到还有另一个基于 Promise 的版本,称为 xml-to-json-promise。
非常感谢您对此的见解,因为当涉及多个异步操作和循环时,我对 Promise 不是很熟悉,因此我最终会为这种情况提供肮脏的解决方案。
问候, J
【问题讨论】:
-
connectors.length === files.length背后的逻辑是什么?一个和另一个有什么关系? -
@trincot 这是一种了解连接器数组何时已完全填充的方法。当要填充的数组长度(连接器)等于文件数时。然后我返回控制台日志,并在调用函数时填充数组。
-
我不明白:每个文件可以有多个属性,那么文件数与属性总数有何关系?另外,请注意
return不会中断处理,仍然可以执行更多readFile回调。 -
这个想法是文件是一个由 x 个文件名组成的数组,旨在由 fs.ReadFile 读取。该 if 语句仅用于检查连接器数组是否已完全填充(它的元素数量与文件数量相同)。但现在我再想一想,你是对的,因为每个文件可以有多个属性。我怎么知道数组何时被填充?感谢您指出这一点
标签: node.js asynchronous promise fs bluebird