2012-12-13 25 views
6

Pracuję nad deck building application dla gry karcianej, w którą gram. Używam localStorage do zapisywania i pobierania talii. Wygląda na to, że działa bezbłędnie w Chrome, ale w przeglądarce Firefox działa niewiarygodnie.localStorage niewiarygodne w przeglądarce Firefox

W pierwszej kolejności wszystko wydaje się działać dobrze, a nawet w przypadku ponownego załadowania. Jeśli jednak dodaję drugą talię i przeładuję, ona znajdzie tylko pierwszą talię. Jeśli usuniemy pierwszą talię, nie znajdzie ona już niczego.

Cała lokalna interakcja z pamięcią masową znajduje się w skryptach/vault.js, którą będę odtworzyć poniżej. czy robię coś źle?

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

Zasadniczo wydaje się, że w pewnym momencie klucze w localStorage stają się "zamrożone" z powodu braku lepszego terminu; localStorage zachowa się poprawnie podczas manipulowania nim, ale zaraz po odświeżeniu strony wydaje się, że powraca do stanu, w którym został zamrożony.

+0

Czy można utworzyć demo http://jsfiddle.net? –

+1

Umieściłem link do samej aplikacji w moim pierwszym poście. Tutaj znowu: http://asmor.com/anr/ – Asmor

+0

Cóż, jeśli jest w skrzypcach, mógłbym pracować z kodem i sprawdzać różne rzeczy. Nie jest to konieczne, ale sprawiłoby, że stałoby się to bardziej prawdopodobne, a inni by z nim majstrowali, aby sprawdzić, czy uda nam się go rozwiązać. –

Odpowiedz

3

Kilka razy spotkałem się z tym samym problemem i na początku nie zauważ powód, dlaczego po prostu nie mógł odczytać localStorage, ale myślę, że znalazłem rozwiązanie tego.

Operacje localStorage są synchroniczne, a różne przeglądarki mają pewne wątpliwości dotyczące sposobu ich obsługi.

W twoim przypadku problem polega na tym, że próbujesz odczytać localStorage, zanim DOM będzie gotowy. Próbowałem go z Firebugiem i dodałem punkt przerwania na początku pliku vault.js i ponownie załaduję stronę, a kiedy kod się zepsuje, sprawdzam kartę-dom i odnajduję właściwość localStorage, a tam jest - pełna lista zapisanych wartości. Kiedy usunąłem punkt przerwania i ponownie załadowałem stronę, wszystkie zniknęły po wczytaniu strony.

To może być błąd w Firefoksie lub innych przeglądarkach, tylko szybciej zainicjalizuj localStorage.

W celu rozwiązania problemu: spróbuj pobrać klucze z localStorage PO DOM jest gotowy.

+0

Dzięki. Chociaż twoja sugestia nie wydaje się być przyczyną tego, to sprawiło, że podążałem tropem, aby znaleźć poniżej hacky. Wciąż chciałbym znaleźć faktyczny powód, dla którego to nie działa i sprawić, że działa poprawnie. – Asmor

+0

To naprawdę bardzo dziwny błąd. Wygląda na to, że jeśli wstrzymasz ładowanie strony przed jej załadowaniem, a następnie wznowisz, są tam wartości, ale jeśli pozwolisz stronie wczytać ją jako pierwszą, znikną. To tak, jakby coś próbowało uzyskać do niego dostęp, zanim będzie gotowe, a przeglądarka nie zainicjuje localStorage. Może warto zgłosić błąd do Mozilli, ale jest to trudne do odtworzenia. – jylauril

+0

Minęło już kilka dni i nie widzę w tym żadnej aktywności, więc zamierzam zrobić to, by zaakceptować odpowiedź. Dzięki, że pomogłeś mi przejść na właściwy tor! – Asmor

0

jylauril jest na dobrej drodze, tak myślę.

Gram z opóźnieniami i zauważam dziwne zachowanie.

O ile wiem, wydaje się, że jeśli w ogóle dotkniesz localStorage przed zakończeniem wykonywania wszystkich skryptów JavaScript, w tym JS z ustawieniem setTimeout, localStorage będzie puste dla tego odsłonięcia strony. Na przykład:

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

konsoli Firebug za:

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 

Myślałem, że mogę być na coś, ale moje teorie dotąd okazały się błędne. Zauważyłem jednak jedną dziwną rzecz. Niezależnie od tego, jak długo czekać, jeśli staram się patrzeć pokłady pierwszy, to nie uda i lokalnej pamięci będzie pusta:

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

Ale jeśli to zrobię ci w odwrotnej kolejności ...

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

Gdybym zalogować localStorage w funkcji, jak to działa dobrze:

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

to działa.Jeśli anuluję to, ale ...

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

To nie działa. To również nie działa, jeśli usunę słowo kluczowe void i po prostu mam localStorage jako instrukcję.

Nie wiem dlaczego, ale console.log (localstorage) wydaje się to naprawić i mogę zadzwonić do localStorage kiedy tylko chcę.

Naprawdę dziwacznie.

EDIT: Znalazłem nieco lepsze rozwiązanie. Wywołanie atrybutu "length" localStorage również działa.

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

Jest to nieco lepiej, że nie ma niczego zalogować ...

+0

Chociaż wydaje się, że to działa, pozostawiam to pytanie w nadziei, że ktoś może wyjaśnić problem i/lub dostarczyć rozwiązanie, które nie jest brzydkim hackerem. – Asmor

-2

• Aby upewnić się, że dane są udostępniane localStorage konsekwentnie na wszystkich stronach HTML: o domenie (lokalnego kontekstu) musi być takim samym. o Upewnij się, że znaczniki >>> są identyczne we wszystkich plikach HTML, o (tylko Firefox) upewnij się, że onPageLoad jest identyczny we wszystkich plikach JavaScript (dodanych w plikach html), tzn. Dodaj te same funkcje do PageLoadEvent.

1

Chociaż jest to stary post, ale pomyślałem, że moje odkrycia mogą pomóc. Miałem również do czynienia z tym samym problemem, więc przeszedłem ten post, próbowałem tego i to jest to, co zauważyłem, w firefoxie, jeśli spróbujesz zrobić wszystko (nawet localStorage.getItem) z localstorage przed window.load to usunie wszystko z to i nie będziesz miał niczego. Więc cokolwiek chcesz ustawić lub uzyskać, zrób to po window.load.

coś takiego

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

BTW starałem się zrobić kilka operacji z localStorage na document.ready przed tym, który zawodzi.

Powiązane problemy