PDA

View Full Version : Problem loading cached localstorage



Makkuro7
28 May 2011, 2:35 PM
Hi,

I am building an application that allows users to store data locally, which they can access later on.
Saving the data to local storage works like charm, but I can't figure out how to load the data from the local storage if the page is refreshed.

When I simply log the store after a page refresh, the data property appears to be empty. (However, the data IS still there, I can access it using any developer plugin)

I tried loading the store by store.load() in the initComponent function of the panel where the data is to be shown, it throws an error "Cannot read property 'id' of null" (with id being the first defined field in my model).

I've spent hours going over docs/forums and can't find a solution, so I'd appreciate any thoughts!

mitchellsimoens
28 May 2011, 4:52 PM
Have you looked at what the cache looks like? More than likely it's because there are duplicate IDs.

Makkuro7
29 May 2011, 2:14 AM
I've cleared the local storage on multiple occasions so that there only a few records, or even just one. So that can't be it, unfortunately.

My store:

Tw.stores.localstore = new Ext.data.Store({

model: 'TweetModel',
proxy: {
type: 'localstorage',
id: 'local-tweets'
},
storeTweet: function(tweet) {

var el = Ext.get(tweet);

this.add({
id: el.select('#id').elements[0].innerText,
from_user: el.select('#user').elements[0].innerText,
profile_image_url: el.select('#avatar').elements[0].src,
created_at: el.select('#date').elements[0].innerText,
text: el.select('#tweet').elements[0].innerText
});

this.sync();
}

The initComp function of the panel where the data is loaded into a list:

initComponent: function() {

//Tw.stores.localstore.load();

var tweets = new Ext.List({
flex: 1,
itemTpl: Tw.twitterConfig.tweetTemplate,
store: Tw.stores.localstore
});

this.items = [tweets];

Tw.views.LocalTweetsPanel.superclass.initComponent.call(this);
}

I feel I'm missing something obvious here.

mitchellsimoens
29 May 2011, 5:31 AM
I understand you cleared it but there is a bug in the Sencha Touch version that the key in localstorage that keeps track of the IDs of the records will have duplicate IDs and I remember having this error. So when you get this error, look at the actual localstorage and inspect if you see the duplicate IDs. I have an override in the bugs section, search for WebStorageProxy in that forum and you should find it.

mitchellsimoens
29 May 2011, 5:32 AM
Also, I deleted the duplicate post in the Ext JS 4 forum yesterday, please don't post the same question more than once.

SimonFlack
29 May 2011, 8:39 AM
This is what I am using to clean things up.


parken.myprogram.cleanLocalStorage = function(localStorageProxyId){
var input = localStorage.getItem(localStorageProxyId);
if(input){
var splitted = input.split(',');
var collector = {};
for (i = 0; i < splitted.length; i++) {
key = splitted[i].replace(/^\s*/, "").replace(/\s*$/, "");
collector[key] = true;
}
var out = [];
for (var key in collector) {
if(localStorage.getItem(localStorageProxyId + '-' + key)){
out.push(key);
}
}
var output = out.join(',');
localStorage.setItem(localStorageProxyId, output);
}
}

I call this when my apps start just to make sure the ids are unique.

Makkuro7
29 May 2011, 9:03 AM
You are completely right about the double IDs! Hope this gets fixed, because the thrown errors don't guide you in the right direction at all.

Sorry about the double post, I was kinda in a rush and only later realized I posted it on the wrong forum, reposted and forgot to delete the original one.

Thanks for your help!

Makkuro7
29 May 2011, 9:06 AM
Simon,

Great snippet! After the many hours I spent frustrating over this (and I'm afraid others have too), no doubt I'll include such a check in my apps as well :)

mitchellsimoens
29 May 2011, 9:14 AM
Also, without my override, you cannot use string IDs if you ever want to do that. We are working on Sencha Touch 2 and I have pushed this issue up. Haven't tested Ext JS 4's localstorage to see if it's fixed there. If it is then it has already been fixed as the data packed is part of Sencha Platform.

basty
9 Jun 2011, 2:26 AM
This error doesn't occur only with duplicated IDs! It shows up also if there was some records in the localstorage which was deleted. If you try to load the store again, this error shows up because Sencha Touch has problems (its a bug probably) to re-/set the recordset-counter in the localstorage properly.

To reproduce the problem, read my post here where I explained it:
Delete/Clear Local Storage record on Mobile Browser (http://www.sencha.com/forum/showthread.php?124536-Delete-Clear-Local-Storage-record-on-Mobile-Browser&p=608539&viewfull=1#post608539)

SimonFlack
9 Jun 2011, 2:32 AM
Hey basty.

The code I posted also cleans up keys that point to deleted records (that no longer exist).

Simon

basty
10 Jun 2011, 5:06 AM
I just tried it and it works great! Thank you very much :-)
Hope this annoying bug will be removed soon.

colworx
10 Aug 2011, 12:22 PM
I experienced both cases in my app -- errors on duplicate IDs and deleted IDs. Thanks SimonFlack for the workaround!

I wasn't able to find a nice solution after digging into the Ext Proxy and Store code. When I update a record like "item.set('qty', current_qty + 1)", and then call sync() on the store, the 'create' operation gets sent to the batch() call when it should be 'update'. This is what's causing multiple IDs in Local Storage. Then on remove, only one of those IDs is removed, leaving extra IDs in the cache and causing the second error.

needsAdd on the records isn't getting set to false in the right place.

anujjain
28 Sep 2011, 10:59 PM
Hello,

I do not have any duplicate and deleted ids in my localstore but still when I try to load cached storage I get this exception:

Uncaught TypeError: Cannot read property 'id' of null

Following is the list of Ids I have in my localstorage:

5649647511735759728
7572481061770300643
-3100060945965780101
-8922344754162749460
-5778145057616355403
4607525170319475196
1609801730728429131
-7193863991648613248
-905530787572748760
-6352212572504932859
5693877913194977215
-6125895471003056661
4431928674812642994
5910245971814222976
-2517271877151376595
-891556716691630751
-7717935222537357967
-1532334964604811609
-2924648465853203055
-7652637592141655918
-324515713633574526
-3383344717992360142
-3517273877144376586
4091975035851855580
1372454250420739036
-4250078735703606588
-5938954978050098991
5510622053519628744
-8127549531845203209
-6373947566344574208
-3993213261276407328
-864720934239907279
-8215046232628498233
392472628000795344
3346457244274465772
-9070185647260979267
-3733991201365986234
-8614610467800588377
-2462843981500520845
-8652813310402942254
-3965156222146297494
-3022209981229651716
-1431744178234801179
2116911743698743403
2797775633663566082
-1626266377300707535
399264123048333818
404239998223733821
-4883811347638166255
3342052585495867905
-6912731013782130767
-8726157114289208958
-1102060755089121263
-7310482542580246857
4821648337412435095
6980717404136929465
-3684122375917209022
-1046247529122829751
-7589873120482493631
25079373504647246
2323236239080956436
701999915946523649
-161617062386191408
-9037810298111046736
1395027956353416358
-6654031654208141738
4920589173842510507
8640661095206689549
4299791198108474890
2494638309148797919
4058425474532677111
-3730848477776133581
7564217665513453569
7899676811943954695
-4690345961843960354
4664901141986429214
-7455370766886100285
-6906883590001546555
-4953387160246525144
2528938829025702097

Any help would be highly appreciated.

Thanks,
Anuj

SimonFlack
28 Sep 2011, 11:02 PM
Try this...

Ext.override(Ext.data.WebStorageProxy,{ // Patching for bugs with localStorage stores
create: function(operation, callback, scope) {
var records = operation.records,
length = records.length,
ids = this.getIds(),
id, record, i;


operation.setStarted();


for (i = 0; i < length; i++) {
record = records[i];


if (record.phantom) {
record.phantom = false;
id = this.getNextId();
} else {
id = record.getId();
}


this.setRecord(record, id);
if (ids.indexOf(id) == -1) {
ids.push(id);
}
}


this.setIds(ids);


operation.setCompleted();
operation.setSuccessful();


if (typeof callback == 'function') {
callback.call(scope || this, operation);
}
}
});

anujjain
28 Sep 2011, 11:12 PM
Thanks Simon
Now I see instead of 80, 160 ids are being created (however I only have 80 records)

for ex. for the id corresponding to 5649647511735759728 following id is also being generated

5649647511735760000 similarly following:

5649647511735760000,7572481061770300000,-3100060945965780000,-8922344754162749000,-5778145057616355000,4607525170319475000...

which does not exists in my record, looks like some kind of round off logic is being applied

anujjain
28 Sep 2011, 11:15 PM
Can it be something related to the range of integer?

SimonFlack
28 Sep 2011, 11:22 PM
No idea... Is your model is using a number for idProperty?

Example:

idProperty: 'EventId',
fields: [{name: 'EventId', type: 'number'},

anujjain
29 Sep 2011, 12:01 AM
Wow, That did the trick

Thanks Simon!

SimonFlack
29 Sep 2011, 12:11 AM
No worries ;-)