2012-12-13 32 views
6

我正在爲我玩的紙牌遊戲工作deck building application。我使用localStorage來保存和檢索套牌。它似乎在Chrome中運行得非常完美,但在Firefox中它的工作並不可靠。localStorage在Firefox中不可靠

在FF中,一開始似乎一切正常,甲板甚至通過重裝持續存在。但是,如果我添加第二套牌並重新加載,它只能找到第一套牌。如果我刪除第一副牌,它不會再找到任何東西。

所有的本地存儲交互都在scripts/vault.js中,我將在下面重現。難道我做錯了什麼?

vault = {}; 
vault.makeKey = function (s) { 
    return "deck:" + s; 
}; 
vault.friendlyName = function(s) { 
    if (s.indexOf("deck:") === 0) { 
     return s.substring(5); 
    } else { 
     return s; 
    } 
}; 
vault.store = function (deck, name) { 
    if (!window.localStorage) { 
     alert("This browser doesn't support local storage. You will be unable to save decks."); 
     return; 
    } 
    var key = vault.makeKey(name); 
    localStorage.setItem(key, deck.export()); 
}; 
vault.retrieve = function (key) { 
    deck.import(localStorage[key]); 
}; 
vault.getDecks = function() { 
    var keys = Object.keys(localStorage), 
     out = [], 
     i, 
     k, 
     name = ""; 
    for (i = 0; i < keys.length; i++) { 
     k = keys[i]; 
     name = vault.friendlyName(k); 
     if (name !== k && localStorage[k]) { 
      out.push({name: name, key: k}); 
     } 
    } 
    out.sort(function (a, b) { 
     return a.name > b.name ? 1 : -1; 
    }); 
    return out; 
}; 
vault.deleteDeck = function (key) { 
    localStorage.removeItem(key); 
}; 

基本上,似乎在某些時候localStorage中的鍵因爲缺乏更好的術語而變得「凍結」 localStorage將在我操縱它時正確運行,但只要刷新頁面,它就會恢復到凍結狀態。

+0

你可以做一個http://jsfiddle.net演示? –

+1

我在第一篇文章中發佈了一個應用程序本身的鏈接。這裏又是:http://asmor.com/anr/ – Asmor

+0

好吧,如果它在小提琴中,我可以使用代碼並檢查不同的東西。這不是必要的,但它會讓我更有可能和其他人一起鼓搗它,看看我們是否可以搞清楚。 –

回答

3

我遇到過幾次相同的問題,起初我沒有注意它爲什麼無法讀取localStorage的原因,但我想我找到了一個解決方案。

localStorage操作都是同步的,不同的瀏覽器對於它們如何處理它們有某些怪癖。

在你的情況,這個問題似乎是你試圖在DOM準備好之前閱讀localStorage。我用Firebug試了一下,我在vault.js文件的開始處添加了一個斷點並重新加載頁面,當代碼中斷時,我檢查dom選項卡並找到localStorage屬性,並且它存在 - 完整的存儲列表值。當我刪除斷點並重新加載頁面時,頁面加載後它們全部消失。

這可能是Firefox或其他瀏覽器中的一個錯誤,只是更快地初始化localStorage。

因此,作爲您的問題的解決方案:嘗試獲取localStorage中的鍵之後DOM準備就緒。

+0

謝謝。雖然你的建議看起來並不是它的原因,但它確實讓我走上了一條尋找下面的黑客解決方案的軌道。我仍然想找到實際的原因,這不起作用,並使其正常工作。 – Asmor

+0

這確實是一個非常奇怪的錯誤。看起來,如果您在加載頁面之前暫停加載頁面,然後恢復,那麼這些值就在那裏,但如果您先讓頁面加載,則頁面將消失。就好像有東西試圖在它準備好之前訪問它並且瀏覽器無法初始化localStorage。可能值得爲Mozilla提供一個bug,但它很難重現。 – jylauril

+0

已經過去了幾天,我沒有看到任何活動,所以我會繼續,並將您標記爲已接受的答案。感謝您幫助我走上正軌! – Asmor

0

jylauril是在正確的軌道上,我認爲。

我一直在玩延遲,並注意到一些奇怪的行爲。

據我所知,似乎在ALL JavaScript完成執行之前,如果您觸摸localStorage,包括JS在執行setTimeout,localStorage對於該pageview將顯示爲空白。例如:

$(window).load(function() { 
    console.log("Waiting 10000ms", new Date()); 
    setTimeout(setDeckSelect, 10000); 
}); 

Firebug的控制檯:

Waiting 10000ms Date {Thu Dec 13 2012 10:35:48 GMT-0500 (Eastern Standard Time)} 
exec.js (line 191) 
getDecks Date {Thu Dec 13 2012 10:35:58 GMT-0500 (Eastern Standard Time)} 
vault.js (line 23) 
>>> localStorage 
0 items in Storage 

我想我可能將要發生什麼,但我的理論迄今已證明是錯誤的。不過,我注意到了一件奇怪的事情。無論我如何的漫長等待,如果我嘗試首先查找甲板,它就會失敗和本地存儲將是空的:

>>> vault.getDecks() 
[] 
>>> localStorage 
0 items in Storage 

但是,如果我做的那些以相反的順序...

>>> localStorage 
8 items in Storage deck:dfs= 
"{"identity":"MakingNews","cards":{}}", deck:ngrngfrn= "{"identity":"BuildingaBetterWorld","cards":{}}", deck:sdfgshsh= "{"identity":"MakingNews","cards":{}}", deck:sdfgdgdfg= "{"identity":"MakingNews","cards":{}}", deck:dfgdfgas= "{"identity":"EngineeringtheFuture","cards":{}}", deck:sdfsga= "{"identity":"MakingNews","cards":{}}", deck:gdgd= "{"identity":"MakingNews","cards":{}}", deck:gfsdfgsdfg= "{"identity":"BuildingaBetterWorld","cards":{}}" 
>>> vault.getDecks() 
[Object { name= "dfgdfgas", key= "deck:dfgdfgas"}, Object { name= "dfs", key= "deck:dfs"}, Object { name= "gdgd", key= "deck:gdgd"}, Object { name= "gfsdfgsdfg", key= "deck:gfsdfgsdfg"}, Object { name= "ngrngfrn", key= "deck:ngrngfrn"}, Object { name= "sdfgdgdfg", key= "deck:sdfgdgdfg"}, Object { name= "sdfgshsh", key= "deck:sdfgshsh"}, Object { name= "sdfsga", key= "deck:sdfsga"}] 

如果我在功能登錄本地存儲,它的工作原理,以及:

vault.getDecks = function() { 
    console.log(localStorage); 
    var keys = Object.keys(localStorage), 
     out = [], 
     i, 
     k, 
     name = ""; 
    for (i = 0; i < keys.length; i++) { 
     k = keys[i]; 
     name = vault.friendlyName(k); 
     if (name !== k && localStorage[k]) { 
      out.push({name: name, key: k}); 
     } 
    } 
    out.sort(function (a, b) { 
     return a.name > b.name ? 1 : -1; 
    }); 
    return out; 
}; 

它的工作原理。如果我將它作廢,雖然...

vault.getDecks = function() { 
    // console.log(localStorage); 
    void localStorage; 
    var keys = Object.keys(localStorage), 
     out = [], 
     i, 
     k, 
     name = ""; 
    for (i = 0; i < keys.length; i++) { 
     k = keys[i]; 
     name = vault.friendlyName(k); 
     if (name !== k && localStorage[k]) { 
      out.push({name: name, key: k}); 
     } 
    } 
    out.sort(function (a, b) { 
     return a.name > b.name ? 1 : -1; 
    }); 
    return out; 
}; 

它不起作用。如果我刪除了void關鍵字,並且僅將localStorage作爲一個語句,它也不起作用。

我不知道爲什麼,但console.log(localstorage)似乎確實解決了這個問題,我可以隨時調用localStorage。

真的很奇怪。

編輯:我發現了一個稍微好一點的解決方案。調用localStorage的'length'屬性也起作用。

vault.getDecks = function() { 
    //Weird hack to make FF load localStorage correctly... 
    localStorage.length; 
    var keys = Object.keys(localStorage), 
     out = [], 
     i, 
     k, 
     name = ""; 
    for (i = 0; i < keys.length; i++) { 
     k = keys[i]; 
     name = vault.friendlyName(k); 
     if (name !== k && localStorage[k]) { 
      out.push({name: name, key: k}); 
     } 
    } 
    out.sort(function (a, b) { 
     return a.name > b.name ? 1 : -1; 
    }); 
    return out; 
}; 

這是因爲它不記錄任何東西好一點......

+0

儘管這似乎起作用,但我仍然希望有人能夠解釋這個問題並且/或者提供一個不是醜陋的解決方案。 – Asmor

-2

•確保localStorage的數據始終在所有的html頁面提供: Ø域(本地上下文)必須相同。 o確保在所有Html文件中保留< <腳本>>標籤相同, o(僅限Firefox)確保onPageLoad在所有JavaScript文件(在html文件中添加)中保持相同,即確保添加相同的函數到PageLoadEvent。

1

雖然這是一箇舊帖子,但認爲我的發現可能有所幫助。我也遇到了同樣的問題,所以我經歷了這個帖子,嘗試了這一點,這是我注意到的,在firefox中,如果你嘗試在window.load之前用localstorage執行任何操作(即使是localStorage.getItem),它也會刪除所有內容它和你不會有任何東西。所以無論你想要做什麼,都要在window.load之後做。

像這樣的事情

$(window).load(function() { 
    //do whatever you want to do with localstorage 
}); 

順便說一句,我想這裏面是失敗前做localStorage的一些操作的的document.ready。