2015-11-05 42 views
-3

我有一個JSON格式的JavaScript對象,需要根據set輸入修改(刪除foo或添加欄等)。此輸入可能具有級聯效果(刪除foo可能需要先根據一組規則刪除foobar)。如果通過級聯的一半中斷,我不希望JavaScript對象有一半的修改,我想回到原來的未修改的對象。修改JavaScript對象裏面的功能,如果錯誤返回到原始

我明顯可以發送一個對象的副本到修改函數中,然後在函數返回錯誤時不會替換原始對象。與此相關的問題是JavaScript對象大約25兆字節,因此它的副本將意味着瀏覽器的內存使用量顯着增加。所以我想在不創建對象副本的情況下執行此操作。我可以將初始對象作爲函數的輸入並遞歸修改,但如果在某些調用後出現錯誤,它可能會在我不需要時返回修改後的對象。

會有辦法做我想做的事嗎?跟蹤更改並在發生錯誤或其他情況後輕鬆撤消它們?謝謝。

+2

「寫少勿多」! –

+1

這裏我關心的是爲什麼你有一個25mb的JavaScript對象... – taxicala

+0

這聽起來像你需要讓你的檢查返回原先的對象,然後跟進你的檢查,實際上修改對象。 –

回答

3

可以創建一個事務數組,記錄對對象所做的每個更改並記錄有關更改的足夠數據,以便可以將其撤消。這並不是一項微不足道的工作。例如,它與字處理程序或電子表格中的撤消功能有點類似。如果您記錄了正確的信息級別並將其保存在一個數組中,則應該可以撤消所有更改。這不是火箭科學,但它是一些編寫和測試的代碼。

正如在評論中提到的,這裏提出的一個更大的問題是關於一個單一的25MB對象,必須通過一個函數來操作。我個人懷疑是否可以將數據分解成更小的部分,並且能夠使用更小的副本來不必編寫整個撤消操作。

此外,值得考慮的是,您是否可以預先足夠的操作來提前知道在修改對象之前代碼是否會失敗。例如,我之前使用的代碼與修改對象的代碼運行所有相同的邏輯,但實際上並未修改對象。這使您可以運行整個操作的預執行,從而確定在實際修改對象之前是否有任何操作失敗。寫得恰當的話,你可以使用相同的代碼進行飛行前的實際修改,只需傳入一個額外的標誌。這是多麼可行取決於修改操作的確切性質,您還沒有透露。

下面是處理特定對象屬性更改的代碼示例。這可以擴展到包括數組操作。

工作演示:http://jsfiddle.net/jfriend00/ohqL0p06/

代碼:

function TransactionSummary() { 
    this.transactions = []; 
} 

TransactionSummary.prototype = { 
    deleteProperty: function(parent, property) { 
     this.rememberTransaction(parent, property, "delete", parent[property]); 
     delete parent[property]; 
    }, 
    modifyProperty: function(parent, property, newVal) { 
     this.rememberTransaction(parent, property, "modify", parent[property]); 
     parent[property] = newVal; 
    }, 
    addProperty: function(parent, property, newVal) { 
     this.rememberTransaction(parent, property, "add"); 
     parent[property] = newVal; 
    }, 
    rememberTransaction: function(parent, property, type, oldVal) { 
     this.transactions.push({parent: parent, property: property, type: type, oldVal: oldVal}); 
    }, 
    undoTransactions: function() { 
     var t; 
     while (this.transactions.length) { 
      t = this.transactions.pop(); 
      switch(t.type) { 
       case "delete": 
       case "modify": 
        t.parent[t.property] = t.oldVal; 
        break; 
       case "add": 
        delete parent[property]; 
        break; 
      } 
     } 
    } 
} 
+0

不幸的是,在這個時候,將對象分解成更小的對象並不是真正的選擇。將來可能會分配給它,但是在其他代碼中需要進行很多重寫,因此到目前爲止,最好的選擇是複製25MB的對象並使內存變得沉重。我承認這是一個非常奇怪的情況,但現在是這樣。 事務數組選項似乎很有趣,但使用它將取決於創建需要多長時間。有沒有一個很好的例子(只是類似於從看看想法)? –

+1

@JediWolf - 我添加了一個可以撤銷更改的事務記錄器示例。 – jfriend00

+0

謝謝,這看起來很有希望。我必須看看我能否在我的最終目標中實現它,但這可能是根據我的情況得到的最好結果。 –

相關問題