Matt Spinks
Matt Spinks

Reputation: 6698

How can get the key of my IndexedDB val using idbKeyval?

I am using the idbKeyval library to save/retrieve data from IndexedDB local storage. I have a function to iterate through all my keys and get each corresponding object. However, when I retrieve each object (val), I need to know its corresponding key (that is how I correlate the object with an element in the DOM). But since the IndexedDB (and idbKeyval) api is asynchronous, I lose reference to the corresponding key. Is there a way that I can retrieve the corresponding key when I retrieve my val? Below is a snippet that better describes what I am trying to do:

var customStore = new idbKeyval.Store('my-db', 'offline-transactions');
idbKeyval.keys(customStore)
    .then(function (keys) {
        for (var i in keys) {
            var key = keys[i];
            var val = idbKeyval.get(key, customStore)
                .then(function (val) {

                    //THIS WORKS:
                    console.log(val);

                    //THIS DOES NOT WORK:
                    console.log(key);
                    //'KEY' IS OUT OF SCOPE HERE
                    //WHAT IS A GOOD WAY TO GET THE CORRESPONDING KEY FOR MY VAL HERE?

                });
        }
    });

And I am using the idbKeyval library: https://github.com/jakearchibald/idb-keyval

Upvotes: 0

Views: 1012

Answers (1)

sheng
sheng

Reputation: 1372

There are two three solutions to this. You can either create an IIFE (the old way) and set a local variable to "copy" the variable from your loop:

.then(function(val) {
    (() => {
        var localKey = key;
        // ...
        // localKey will be preserved since it's encapsulated
        // in its own functional scope
    })();
}

Or you can use the more elegant Array.forEach ES6 method:

keys.forEach((key) => {
    var val = // ...
    // No need to copy key here since we're in a new functional
    // scope by the nature of .forEach
});

Both methods essentially work the same -- you're preserving a variable by creating a new functional scope for each iteration of your loop.

Hope that helps clarify things a little.

EDIT

I missed the simplest* solution: using let or const in your for loop instead of var. This works because let and const have block scope instead of function scope. This article helps explain that. So:

for (var i in keys) {
    const key = keys[i];
    // ...
    // key will be preserved in block
}

Personally, I'd prefer Array.forEach just because it looks simpler and protects you from ever having to worry about what scope you're in.

*Simplest: I had no idea until a moment ago.

Upvotes: 1

Related Questions