Get all values from Ionic storage

I have below code to get all items from ionic storage.

getAllFavorites(){
let items=[];

this.storage.forEach((v,k)=>{

  if(this.IsJsonString(v)) //checking if value is valid json
    {
  console.log('value',v);
  console.log('key',k);          
      items.push(JSON.parse(v));
    }
})
return items.length? items:null;  // this always returns null

}

with above code method getAllFavorites always returns null…May be I’m not utilizing then method on foreach but how do I return all stored items if I use then method on foreach?

My ultimate goal is to return all items saved in storage.

I’m going to guess that v has already been deserialized by the time you receive it, so that isJsonString check will fail virtually always.

Nope…console.log statement inside if statement are getting executed…

You have two problems.

The first we have already discussed. Unless you are explicitly stringifying things (which you shouldn’t be doing), you shouldn’t be caring about whether something is a valid JSON string. You are the one putting things into storage; you know they are valid.

The second is that you cannot do this:

asynchronousThing().then(() => {
  doWhatever();
});
expectWhateverToHaveBeenDoneByNow();

Anything dependent on your forEach loop must be inside the then block. If you had typed the return values of all your functions, at build time you would have been informed that you are attempting to return a synchronous value in an impossible position. You can’t return items out of this function, no matter what you do. The very first word in a function like your getAllFavorites() must be return, and no matter how inconvenient that may be for whoever is calling it, they must deal with it.

Okay for the first point, I removed check for valid json.

for the second point, I understand what you are saying…but then I’m not getting the clue that how can I return all values of the storage in that case where I have to place first statement as return??

and what is the standard way of getting all values from the local storage? This must be common requirement in all apps…

okay resolved it like below. Let me know if this is good way.

getAllFavorites(){
let items=[];
return new Promise(resolve=>{
this.storage.forEach((v,k)=>{
console.log(‘value’,v);
console.log(‘key’,k);
items.push(v);
}).then(()=>{
resolve(items);
})
})
}

It invokes the explicit promise construction antipattern, so you could do it more cleanly like so:

let items = [];
return this.storage.forEach(v => items.push(v)).then(() => items);

However, in my testing, forEach seems to be buggy using the IndexedDB driver, and I was only getting a a single value before the forEach promise resolved. If you want something more robust that will work in both browser and (potentially, I didn’t check) on device, how about this alternative?

return this.storage.keys()
  .then(keys => Promise.all(keys.map(k => this.storage.get(k))));
2 Likes

Damn. Getting down into the frikkin weeds. Thanks very much for this.

Just came into this and wanted to clarify that forEach is not buggy… just you are cutting the loop returning the items.push(v) without curly brackets. The correct way would be:

    let items: any = []
    return this.storage.forEach(v => {
      items.push(v)
    }).then(() => Promise.resolve(items));