Node.js我的函数显示了未定义的字典值,尽管它被赋值了



我是javascript的新手,所以如果以前有人问我这个问题,我很抱歉。

我有这个函数,我用它来读取json文件。

const jsonfile = require('jsonfile');
function readData(fileName: string, callback) {
jsonfile.readFile(".\data\" + fileName + ".json", 'utf8', function (err, data) {
if (err) console.error(err)
callback(null, data);
})
}

然后我用这个来称呼它:

// Read JSON files
var fileList = ["guides"];
var files = {};
for (let i = 0; i < fileList.length; i++) {
readData(fileList[i], function (err, result) {
if (err) throw err;
files[i] = result;
})
}

但当我:

console.log(files['guides']);

则返回CCD_ 1。有人能帮我解决这个问题吗?非常感谢。

jsonfile.readFile函数的回调函数被异步调用,并且console.log语句被同步执行。

异步代码在javascript代码的同步执行结束后执行;因此,在files对象中添加guides属性之前,console.log语句正在记录files['guides']。这就是为什么你没有定义。

下面的代码示例显示了这个问题的作用:

let a = 1;
setTimeout(() => {
a = 2; 
}, 100);
console.log(a);

上面的代码段输出1,因为setTimeout的回调函数是异步调用,即在执行了undefined0语句之后的,并且在执行console.log语句时,a的值为1

解决方案

为了确保在读取所有文件并填充files对象之后记录files["guides"],可以从readData函数返回promise。

以下代码展示了如何围绕readData函数创建promise包装器:

function readData(fileName) {
return new Promise((resolve, reject) => {
jsonfile.readFile(".\data\" + fileName + ".json", 'utf8', function (err, data) {
if (err) reject(err);
else resolve(data);
})
}
};

现在您可以将上述函数调用为:

Promise.all(fileList.map(filePath => readData(filePath)))
.then(dataFromAllFiles => {
console.log(dataFromAllFiles);
})
.catch(error => console.log(error));

有用链接:

  • 异步JavaScript

  • Promises 的优雅异步编程

  • 使用Promises

最新更新