我正在阅读有关从文件中require
JSON对象的信息。我可以正确读取 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
。这是因为setTimeout
和fs.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
,要么使用 withreadFile
和writeFile
重写代码并使用回调。