如果我从文件中读取 JSON 数组,那么我会取出旧的未更改数组



我正在阅读有关从文件中requireJSON对象的信息。我可以正确读取 JSON,但在我向其添加数据并将其保存到文件中后,重新要求不会获取更新的 JSON,而是检索旧文件。有人可以解释为什么会这样吗?我该如何解决这个问题?

var file = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'] + "\AppData\Roaming\BetterDiscord\plugins\Test.json";
var json = require(file);
console.log(JSON.stringify(json.img));
json.img.push({name:"Test"});
console.log(JSON.stringify(json.img));
save(JSON.stringify(json), file);
json = require(file);
console.log(JSON.stringify(json.img));

这是save方法:

var save = function(value, file){
var fs = require('fs');
fs.writeFile(file, value, function(err) {
if (err) {
console.log(err);
}
});
};

这是输出:

Output 1: [{"name":"A"},{"name":"B"}]
Output 2: [{"name":"A"},{"name":"B"}, {"name":"Test"}]
Output 3: [{"name":"A"},{"name":"B"}]

你的代码有两个主要问题。首先,save是一个异步函数。这意味着您直接编写的任何代码都将在完成之前运行。在这方面,它的工作原理就像setTimeout一样。

console.log(1);
setTimeout(function() {
console.log(2);
}, 100);
console.log(3);

请注意它如何在2之前输出3。这是因为setTimeoutfs.writeFile一样,是异步的。为了确保在代码完成后运行代码,您可以传递回调或使用 Promises(不在此问题的范围之内,但非常有用)。所以你的代码可能看起来像这样。

const save = (path, cb) => {
setTimeout(() => {
cb();
}, 100);
};
let path = 'path/to/file';
save(path, () => {
console.log(`Saved ${path}`);
});
console.log(`Saving ${path}...`);

这整个事情也可以通过使用sync版本的writeFile.

fs.writeFileSync(file, value);

下一个问题源于require如何缓存结果。这样做是因为它旨在加载模块,并且大多数时候它们不会动态更改。相反,请直接从系统加载文件。这也可以异步或同步使用。以下是我如何使用同步代码重写代码(尽管异步通常更可取)。

var fs = require('fs');
var save = function(value, file){
return fs.writeFileSync(file, value);
};
var file = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'] + "\AppData\Roaming\BetterDiscord\plugins\Test.json";
var obj = JSON.parse(fs.readFileSync(file, 'utf8'));
obj.img.push({name:"Test"});
console.log(JSON.stringify(obj.img));
save(JSON.stringify(obj), file);
obj = JSON.parse(fs.readFileSync(file, 'utf8'));
console.log(JSON.stringify(obj.img));

require将缓存该文件。使用fs.readFileSync方法再次读取文件,而不是必需的。

json = fs.readFileSync(file);

此外,正如@MikeC指出的那样,您正在异步写入文件,因此要么将其切换为同步版本writeFileSync,要么使用 withreadFilewriteFile重写代码并使用回调。

最新更新