2014-05-09 32 views
1

我在玩弄嘗試通過編寫配方應用程序來學習Node + Express和Angular。Node.js json文件被另一個調用覆蓋

我在節點存儲食譜的陣列,並在JSON文件作爲我的數據存儲成分的陣列,並且我有一個簡單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應用程序應該能夠支持這樣的請求。有沒有辦法鎖定文件或我應該採取的另一種方法?

+1

但是,這就是節點是如何工作的......「非阻塞」 – Dalorzo

回答

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() 
}; 
+0

幾乎完美,只需要將running = true行向下移動兩行即可,或者在隊列末尾保持設置爲true。非常感謝您的幫助! – littlecharva