我正在尝试通过编写配方应用程序来学习Node + Express和Angular。
我在json文件中存储了一系列食谱和一系列成分作为我的数据存储,我在Node中有一个简单的saveMeal()和saveIngredient()方法,如下所示:
exports.saveIngredient = function(req, res) {
var ing = req.body;
console.log('Saving Ingredient: ' + JSON.stringify(ing, null, 4));
fs.readFile('./data/data.json', 'utf-8', function (error, data) {
var mData = JSON.parse(data);
ing.id = generateId(ing.name, mData.ingredients);
mData.ingredients.push(ing);
fs.writeFile('./data/data.json', JSON.stringify(mData, null, 4), function(err) {
res.writeHead(200, { 'Content-Type': 'text/json' });
res.end(ing.id, 'utf-8');
});
});
};
我遇到的问题是Angular应用程序会触发一系列回调节点的调用以保存每个成分,而无需等待每个成分完成,然后再触发下一个调用,尽管每个调用返回一个成分的id ,只有最后一个成分保存,所以最后一次调用必须覆盖它之前的数据。
我知道我可以改变Angular应用程序在保存下一个成分之前等待响应的方式,但我觉得Node应用程序应该能够支持这样的请求。有没有办法锁定文件或我应采取的其他方法?
答案 0 :(得分:2)
问题是您正在运行多个请求以同时保存文件。
保存A到达并异步加载文件 - 在此期间保存B到达并在保存A提交更改之前加载。
解决方案是一次只运行其中一个保存请求 - 类似这样(我没有测试过),它按顺序保存一系列保存函数和块:
// an array of functions in the queue
var fnBuffer = []
// are we currently running a function in the queue
var running = false
// run the queue one at a time - on finish run again
function runSave(){
if(running) return
running = true
var nextfn = fnBuffer.shift()
if(!nextfn) return
nextfn(function(){
running = false
runSave()
})
}
exports.saveIngredient = function(req, res) {
// push the function onto the queue
fnBuffer.push(function(callback){
// this is the original code - the only extra is the callback
var ing = req.body;
console.log('Saving Ingredient: ' + JSON.stringify(ing, null, 4));
fs.readFile('./data/data.json', 'utf-8', function (error, data) {
var mData = JSON.parse(data);
ing.id = generateId(ing.name, mData.ingredients);
mData.ingredients.push(ing);
fs.writeFile('./data/data.json', JSON.stringify(mData, null, 4), function(err) {
res.writeHead(200, { 'Content-Type': 'text/json' });
res.end(ing.id, 'utf-8');
// running this callback tells the queue to run the next function
callback()
});
});
})
// trigger the queue
runSave()
};