IndexedDB: загрузка данных из файла JSON при вызове onUpgradeNeeded - PullRequest
1 голос
/ 06 мая 2019

На моем веб-сайте есть файл JSON, содержащий данные, предназначенные для передачи в локальную IndexedDB моих пользователей.Я ищу способ загрузить этот файл JSON, когда обновление действительно необходимо.

Чтобы уточнить, я планирую, чтобы мой веб-сайт по возможности почти полностью использовал локально сохраненные данные моих пользователей, подобно приложению.Они должны загружать файл JSON только при наличии нового обновления IDB.

До сих пор я пытался выполнить это, запустив событие onUpgradeNeeded как асинхронную функцию.

if (!window.indexedDB) {
    window.alert("Your browser doesn't support a stable version of IndexedDB, which is required for most functions of this website. For the best support, please use the latest version of Chrome, Firefox, or Safari.");
}

else {
  var dbVer = 39; //IDB Version (int only)
  var recipeObject; //instantiate global variable for module object import
  var recipeArray = []; //instantiate global array for module import
  var recipeDBver; //instantiate global variable for actual database version (TODO: implement version checking)
  var upgradeNeeded = false;
  var clearNeeded = false;
  var openRequest = indexedDB.open('recipeDatabase', dbVer);

  console.log("IDB.js running");

  openRequest.onsuccess = function(e) {
    console.log('Running onSuccess');
  };

  openRequest.onerror = function(e) {
    console.log('Open Request ERROR');
    console.dir(e);
  };

  openRequest.onupgradeneeded = async function(e) {
    var db = e.target.result;

    console.log('Running onUpgradeNeeded');

    db.onerror = function(errorEvent) {
      console.log("onUpgradeNeeded ERROR");
      return;
    };

    importObject = await import("/resources/recipeDB.js");

    //TODO: remove debugging
    console.log('Module loaded');
    console.log(importObject);
    recipeObject = importObject.default;
    console.log(recipeObject);
    recipeDBver = recipeObject.recipeDBver;
    console.log(recipeDBver);
    recipeArray = recipeObject.recipeArray;
    console.log(recipeArray);

    upgradeNeeded = true;

    if (!db.objectStoreNames.contains('drinks')) {
      var storeOS = db.createObjectStore('drinks', {keyPath: 'id'});
      storeOS.createIndex('name', 'name', { unique: false });
      storeOS.createIndex('type', 'type', { unique: false });
      storeOS.createIndex('subtype', 'subtype', { unique: false });
      storeOS.createIndex('tags', 'tags', { unique: false });
    }
    else {
      clearNeeded = true;
    }

    console.log('IDB Upgrade Needed: ' + upgradeNeeded);
    console.log('IDB Clear Needed: ' + clearNeeded);
    db = e.target.result;
    if (clearNeeded == true) {
      clearData();
    }
    else if (upgradeNeeded == true) {
      for (var i = 0; i < recipeArray.length; i++) {
        addItem(recipeArray[i]);
      }
    }

  };


  function clearData() {

    var db = openRequest.result;

    var transaction = db.transaction(["drinks"], "readwrite");

    var objectStore = transaction.objectStore("drinks");

    var objectStoreRequest = objectStore.clear();

    objectStoreRequest.onerror = function(e) {
      console.log('Error clearing data. ', e.target.error.name);
      console.dir(e);
    };

    objectStoreRequest.onsuccess = function(e) {
      console.log('Data cleared successfully.')
      for (var i = 0; i < recipeArray.length; i++) {
        addItem(recipeArray[i]);
      }
    };

  }

  function addItem(curItem) {
    var db = openRequest.result;
    var transaction = db.transaction(['drinks'], 'readwrite');
    var store = transaction.objectStore('drinks');
    var item = curItem;

    var request = store.add(item);

    request.onerror = function(e) {
      console.log('Error', e.target.error.name);
      console.dir(e);
    };
    request.onsuccess = function(e) {
      console.log('Item added: ' + curItem.name);
    };
  }



}

Консоль возвращает следующее: Console screenshot

Я предполагаю, что событие onUpgradeNeeded истекло до истеченияФайл JSON может загружаться.

Есть ли способ отложить тайм-аут?Если нет, кто-нибудь знает лучший способ добиться того, что я пытаюсь сделать?

Ответы [ 2 ]

0 голосов
/ 09 мая 2019

Проблема видна из того, что вы видите в консоли. Сначала мы получаем IDB.js is running, а затем вы переходите к своему обработчику onupgradeneeded, но затем, вместо того, чтобы что-либо из этой консоли функций регистрировалось, мы сразу же видим, как запускается обработчик onsuccess. Причина этого в том, что вы определили свой обработчик onupgradeneeded как async, что означает, что эта функция по существу останавливает выполнение в строке await import("/resources/recipeDB.js");, пока она ожидает разрешения импорта. По сути это означает, что события IDB касаются того, что onupgradeneeded выполнено, и оно должно перейти в onsuccess. Как сказал Джош выше, это потому, что onupgradeneeded необходимо разрешить синхронно .

Что вы можете сделать, чтобы обойти это, это:

  • Сделать onupgradeneeded синхронным
  • Обновление схемы IDB (создание нового хранилища объектов и индексов)
  • Импортируйте данные и после успешного импорта вставьте их в базу данных

Это одна из трудностей в использовании IndexedDB: она не основана на обещаниях, поэтому использование функций async на основе обещаний не всегда хорошо с ней работает. Я обычно нахожу, что эти недостатки требуют большего количества кода для их обработки (например, использование вызовов .then(), чтобы я мог иметь синхронные обработчики событий, в то же время выполняя необходимые асинхронные действия).

0 голосов
/ 06 мая 2019

Обработчик события onupgradeneeded должен завершиться синхронно. Точнее, запросы к / внутри запущенной транзакции изменения версии должны запускаться в том же тике цикла событий, что и при запуске транзакции изменения версии.

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

...