IndexedDB требуется время для инициализации внешней переменной области видимости db, которая необходима в другой функции - PullRequest
0 голосов
/ 19 сентября 2019

Я открываю базу данных, используя indexedDB, используя javascript для хранения записи в дневнике.Я делаю три вещи с базой данных: отображать все записи, добавлять записи и удалять записи.

Сбой при попытке создать транзакцию, потому что 'db' это 'undefined.'Я ожидал, что db будет определено ко времени, когда код пытается создать транзакцию.

Ошибка вызвана в строке с кодом:

      const getObjectStore = (storeName, mode) => {
        console.log('db: ', db);
        const tx = db.transaction(storeName, mode); // error is thrown because db is undefined
        return tx.objectStore(storeName);
      };

Я пытался поместить console.log вразные места, чтобы увидеть, что не так.Я обнаружил, что БД требует времени, прежде чем он будет определен ответом onsuccess или onupgradeeeded.Я не вижу другого способа определить БД до его использования.Можете ли вы показать мне, как я могу убедиться в назначении БД перед его использованием?

Выходы:

> adding something in the diary
> db from getObjectStore:  undefined
> Uncaught TypeError: Cannot read property 'transaction' of undefined
    at getObjectStore (script.js:35)
    at Object.setAnEntry [as add] (script.js:62)
    at script.js:81
    at script.js:215
getObjectStore @ script.js:35
setAnEntry @ script.js:62
(anonymous) @ script.js:81
(anonymous) @ script.js:215
> there is indexeddb!
> db:  IDBDatabase {name: "medDiary", version: 1, objectStoreNames: DOMStringList, onabort: null, onclose: null, …}

Весь код, с которым я работаю:

  // DATABASE FOR THE DIARY

  const Dairy = (() => {
    if (window.indexedDB) {
      let db;
      const DB_NAME = 'Dairy';
      const DB_VERSION = 1;
      const DB_STORE_NAME = 'diaries';
      const request = window.indexedDB.open(DB_NAME, DB_VERSION);

      request.onerror = () => {
        console.log('Error requesting to open database permission denied.');
      };
      request.onsuccess = (event) => {
        console.log('there is indexeddb!');
        db = event.target.result;
        console.log('db: ', db);
        db.onerror = (evt) => {
          console.error(`Database error: ${evt.target.errorCode}`);
        };
      };

      request.onupgradeneeded = (event) => {
        db = request.result;
        const store = event.currentTarget.result.createObjectStore(DB_STORE_NAME, { keyPath: 'date' });
        store.createIndex('subject', 'subject', { unique: false });
        store.createIndex('date', 'date', { unique: true });
        store.createIndex('description', 'description', { unique: false });
      };

      const getObjectStore = (storeName, mode) => {
        console.log('db from getObjectStore: ', db);
        const tx = db.transaction(storeName, mode);
        return tx.objectStore(storeName);
      };

      const getAllEntries = () => new Promise((resolve) => {
        const result = [];
        const store = getObjectStore(DB_STORE_NAME, 'readonly');
        const req = store.openCursor();

        req.onsuccess = (evt) => {
          const cursor = evt.target.result;

          if (cursor) {
            const retrive = store.get(cursor.key);
            retrive.onsuccess = function (evt) {
              const value = evt.target.result;
              result.append(value);
            };
            cursor.continue();
          } else {
            console.log('No more entries');
            resolve(result);
          }
        };
      });

      const setAnEntry = (value) => {
        const store = getObjectStore(DB_STORE_NAME, 'readwrite');
        store.put(value);
      };
      const removeAnEntry = (value) => {
        const store = getObjectStore(DB_STORE_NAME, 'readwrite');
        store.remove(value);
      };

      return {
        all: getAllEntries,
        add: setAnEntry,
        remove: removeAnEntry,
      };
    }
    alert("Your browser doesn't support a stable version of IndexedDB. Dairy related features will not be available.");
    return {};
  })();

  console.log('adding something in the diary');
  console.log('... ', Dairy.add({ subject: 'hello', description: 'bluh bluh', date: Date() }));
  console.log('show all: ', Dairy.all());

1 Ответ

0 голосов
/ 19 сентября 2019

Вы можете использовать обещание, чтобы открыть БД:

let promise = new Promise(function(resolve, reject)
        {
            //check for support
            if (!('indexedDB' in window)) {
                //console.log('This browser doesn\'t support IndexedDB');
                reject("indexedDB not supported");
            }

            var request = indexedDB.open(dbName, dbVersion);
            request.onerror = function (event) {
                reject("Error opening DB");
            };
            request.onsuccess = function (event) {
                console.log("opened!");
                db = request.result;
                resolve(true);
            };
        });

И затем вы можете использовать:

promise
    .then(
        result => {
            your stuff here sine the DB is now open!!
        },
        error => console.log(error)
    )

Параметр, переданный для разрешения, будет доступен как «результат».

Для использования в формате вашего модуля: Добавьте функцию инициализации:

async function init()
{
    let promise = new Promise(function(resolve, reject)
        {
            //check for support
            if (!('indexedDB' in window)) {
                //console.log('This browser doesn\'t support IndexedDB');
                reject("indexedDB not supported");
            }

            var request = indexedDB.open(dbName, dbVersion);
            request.onerror = function (event) {
                reject("Error opening DB");
            };
            request.onsuccess = function (event) {
                console.log("opened!");
                db = request.result;
                resolve(true);
            };
        });
    let result = await promise;
}

Ваш модуль переписан:

const Dairy = (() => {
    if (window.indexedDB)
    {
        let db;
        const DB_NAME = 'Dairy';
        const DB_VERSION = 1;
        const DB_STORE_NAME = 'diaries';
        async function init()
        {
            let promise = new Promise(function(resolve, reject)
            {
                const request = window.indexedDB.open(DB_NAME, DB_VERSION);

                request.onerror = () => {
                    reject('Error requesting to open database permission denied.');
                };
                request.onsuccess = (event) => {
                    console.log('there is indexeddb!');
                    db = event.target.result;
                    console.log('db: ', db);
                    db.onerror = (evt) => {
                        reject("Database error: ${evt.target.errorCode}");
                    };
                    resolve(true);
                };

                request.onupgradeneeded = (event) => {
                    db = request.result;
                    const store = event.currentTarget.result.createObjectStore(DB_STORE_NAME, { keyPath: 'date' });
                    store.createIndex('subject', 'subject', { unique: false });
                    store.createIndex('date', 'date', { unique: true });
                    store.createIndex('description', 'description', { unique: false });
                };
            });
            return promise;
        }

      const getObjectStore = (storeName, mode) => {
        console.log('db from getObjectStore: ', db);
        const tx = db.transaction(storeName, mode);
        return tx.objectStore(storeName);
      };

      const getAllEntries = () => new Promise((resolve) => {
        const result = [];
        const store = getObjectStore(DB_STORE_NAME, 'readonly');
        const req = store.openCursor();

        req.onsuccess = (evt) => {
          const cursor = evt.target.result;

          if (cursor) {
            const retrive = store.get(cursor.key);
            retrive.onsuccess = function (evt) {
              const value = evt.target.result;
              result.append(value);
            };
            cursor.continue();
          } else {
            console.log('No more entries');
            resolve(result);
          }
        };
      });

      const setAnEntry = (value) => {
        const store = getObjectStore(DB_STORE_NAME, 'readwrite');
        store.put(value);
      };
      const removeAnEntry = (value) => {
        const store = getObjectStore(DB_STORE_NAME, 'readwrite');
        store.remove(value);
      };

      return {
        all: getAllEntries,
        add: setAnEntry,
        remove: removeAnEntry,
        init: init
      };
    }
    alert("Your browser doesn't support a stable version of IndexedDB. Dairy related features will not be available.");
    return {};
  })();
  Dairy.init()
    .then(
        result => {
            console.log('adding something in the diary');
            console.log('... ', Dairy.add({ subject: 'hello', description: 'bluh bluh', date: Date() }));
            console.log('show all: ', Dairy.all());
        },
        error => console.log(error)
    );
...