2012-12-13 15 views
6

Sto lavorando a un deck building application per un gioco di carte che gioco. Sto usando localStorage per salvare e recuperare i deck. Sembra funzionare perfettamente in Chrome, ma in Firefox funziona in modo inaffidabile.localStorage inaffidabile in Firefox

In FF, tutto sembra funzionare bene in un primo momento, il ponte persiste anche attraverso una ricarica. Tuttavia, se aggiungo un secondo mazzo e ricarico, trova solo il primo mazzo. Se cancello il primo mazzo, non trova più nulla.

Tutta l'interazione di archiviazione locale è in script/vault.js, che riprodurrò di seguito. Sto facendo qualcosa di sbagliato?

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); 
}; 

In sostanza, sembra che ad un certo punto le chiavi in ​​localStorage vengono 'congelate' per mancanza di un termine migliore; localStorage si comporterà correttamente mentre lo manipolo, ma appena aggiorno la pagina sembra tornare a qualsiasi stato in cui è stato congelato.

+0

Puoi fare una demo di http://jsfiddle.net? –

+1

Ho pubblicato un collegamento all'applicazione stessa nel mio primo post. Eccolo di nuovo: http://asmor.com/anr/ – Asmor

+0

Beh, se si tratta di un violino, potrei lavorare con il codice e controllare cose diverse. Non è necessario, ma renderebbe più probabile me stesso e alcuni altri armeggiare con esso per vedere se riusciamo a capirlo. –

risposta

3

Ho incontrato questo stesso problema un paio di volte e all'inizio non l'ho fatto nota il motivo per cui non è stato possibile leggere il localStorage, ma penso di aver trovato una soluzione per questo.

Le operazioni localStorage sono tutte sincrone e diversi browser hanno certe stranezze su come gestirle.

Nel tuo caso, il problema sembra essere che stai cercando di leggere il localStorage prima che il DOM sia pronto. L'ho provato con Firebug e ho aggiunto un punto di interruzione all'inizio del file vault.js e ho ricaricato la pagina e quando il codice si interrompe, controllo la dom-tab e trovo la proprietà localStorage, ed eccola lì: l'elenco completo di stored valori. Quando ho rimosso il punto di interruzione e ricaricato la pagina, erano tutti spariti una volta caricata la pagina.

Questo potrebbe essere un bug in Firefox o in altri browser solo inizializzare il localStorage più velocemente.

Quindi, come soluzione al problema: provare a recuperare le chiavi da localStorage DOPO che il DOM è pronto.

+0

Grazie. Mentre il tuo suggerimento non sembra essere la causa di ciò, mi ha fatto andare su una pista per trovare una soluzione hacky di seguito. Mi piacerebbe ancora trovare il vero motivo per cui questo non funziona e farlo funzionare correttamente. – Asmor

+0

È davvero un bizzarro bug. Sembra che se metti in pausa il caricamento della pagina prima che sia caricata, e poi riprendi, i valori ci sono, ma se lasci che la pagina si carichi per prima, non ci sono più. È come se qualcosa provasse ad accedervi prima che sia pronto e il browser non riesce a inizializzare il localStorage. Potrebbe essere utile archiviare un bug per Mozilla, ma è difficile riprodurlo. – jylauril

+0

Sono passati un paio di giorni e non vedo alcuna attività su questo, quindi vado avanti e ti segnalo come risposta accettata. Grazie per avermi aiutato a seguire la strada giusta! – Asmor

0

jylauril è sulla strada giusta, penso.

Ho giocato con ritardi e ho notato un comportamento strano.

Per quanto posso dire, sembra che se tocchi localStorage affatto prima che TUTTO JavaScript abbia completato l'esecuzione, incluso JS che fa setTimeout, localStorage apparirà vuoto per quella visualizzazione di pagina. Per esempio:

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

console di 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 

ho pensato che avrei potuto essere a qualcosa, ma le mie teorie finora sono smentiti. Una cosa strana che ho notato, però. Indipendentemente da quanto tempo mi aspetta, se provo a guardare in alto i ponti prima, fallirà e storage locale sarà vuoto:

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

Ma se faccio quelli in ordine inverso ...

>>> 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"}] 

Se accedo localStorage nella funzione, funziona così:

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; 
}; 

funziona.Se lo annullo, però ...

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; 
}; 

Non funziona. Inoltre, non funziona se rimuovo la parola chiave void e ho solo localStorage come dichiarazione.

Non so perché, ma console.log (localstorage) sembra risolvere il problema, e posso chiamare il localStorage ogni volta che voglio.

Davvero spaventoso.

MODIFICA: Ho trovato una soluzione leggermente migliore. Funziona anche l'attributo 'length' di localStorage.

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; 
}; 

Questo è un po 'meglio in quanto non registra nulla ...

+0

Anche se sembra funzionare, sto lasciando questa domanda aperta nella speranza che qualcuno possa spiegare il problema e/o fornire una soluzione che non sia un brutto scherzo. – Asmor

-2

• Per garantire che i dati localStorage è reso disponibile in modo coerente in tutte le pagine html: o Domain (contesto locale) deve essere lo stesso o Assicurati di mantenere lo script < < >> identico in tutti i file Html, o (solo Firefox) assicurati che onPageLoad sia mantenuto identico in tutti i file JavaScript (aggiunti all'interno di file html), ad esempio assicurati di aggiungere le stesse funzioni a PageLoadEvent.

1

Anche se questo è un vecchio post ma ho pensato che le mie scoperte potrebbero aiutare. Anch'io stavo affrontando lo stesso problema quindi ho passato questo post, ho provato questo e questo è quello che ho notato, in firefox se provi a fare qualcosa (anche un localStorage.getItem) con localstorage prima che window.load rimuova tutto da e tu non avrai nulla. Quindi qualunque cosa tu voglia fare, impostare o ottenere, fallo dopo window.load.

Qualcosa di simile

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

BTW stavo cercando di fare alcune operazioni con localStorage a document.ready prima di questo, che stava venendo a mancare.

Problemi correlati