Как можно получить ключ моего значения IndexedDB, используя idbKeyval?

#javascript #indexeddb

#javascript #indexeddb

Вопрос:

Я использую библиотеку idbKeyval для сохранения / извлечения данных из локального хранилища IndexedDB. У меня есть функция для перебора всех моих ключей и получения каждого соответствующего объекта. Однако, когда я извлекаю каждый объект ( val ), мне нужно знать соответствующий ему ключ (именно так я соотношу объект с элементом в DOM). Но поскольку api IndexedDB (и idbKeyval) является асинхронным, я теряю ссылку на соответствующий ключ. Есть ли способ, которым я могу получить соответствующий, key когда я получаю свой val ? Ниже приведен фрагмент, который лучше описывает то, что я пытаюсь сделать:

 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?

                });
        }
    });
  

И я использую библиотеку idbKeyval:https://github.com/jakearchibald/idb-keyval

Ответ №1:

Существуют два три решения для этого. Вы можете либо создать IIFE (старым способом), либо установить локальную переменную для «копирования» переменной из вашего цикла:

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

Или вы можете использовать более элегантный Array.forEach метод ES6:

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

Оба метода по сути работают одинаково — вы сохраняете переменную, создавая новую функциональную область для каждой итерации вашего цикла.

Надеюсь, это поможет немного прояснить ситуацию.

Редактировать

Я пропустил самое простое * решение: использование let or const в вашем цикле for вместо var . Это работает, потому что let и const имеют область блока вместо области функции. Эта статья помогает объяснить это. Итак:

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

Лично я предпочел бы Array.forEach просто потому, что это выглядит проще и защищает вас от необходимости беспокоиться о том, в какой области вы находитесь.

* Самый простой: я понятия не имел до недавнего времени.