Javascript IndexedDB需要时间来初始化另一个函数所需的外部作用域变量db

Javascript IndexedDB需要时间来初始化另一个函数所需的外部作用域变量db,javascript,indexeddb,Javascript,Indexeddb,我正在使用indexedDB打开一个数据库,使用javascript保存日记条目。我对数据库做了三件事:显示所有条目、添加条目和删除条目 它尝试创建事务时失败,因为“db”是“未定义的”。我希望在代码尝试创建事务时定义db 代码为的行出现错误: const getObjectStore = (storeName, mode) => { console.log('db: ', db); const tx = db.transaction(store

我正在使用indexedDB打开一个数据库,使用javascript保存日记条目。我对数据库做了三件事:显示所有条目、添加条目和删除条目

它尝试创建事务时失败,因为“db”是“未定义的”。我希望在代码尝试创建事务时定义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放在不同的地方,看看哪里出了问题。我发现db在被onsuccess响应或OnUpgradeRequired响应定义之前需要一段时间。在使用db之前,我看不到任何其他定义db的方法。你能告诉我,在使用db之前,我如何保证分配db

产出:

> 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());

您可以使用承诺打开数据库:

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)
    )
传递给resolve的参数将作为“result”可用

要在模块格式中使用: 添加初始化函数:

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)
    );

我试图使用模块模式,我必须返回一个设置为日记的对象。如何从then()返回一个值以设置为Diary?为您的模块创建一个init函数。与异步函数init()类似。里面你可以用:让结果=等待承诺;这将等待承诺的结束。我将更新answer我不明白异步函数init()是如何使用的,或者是如何与您以前的答案结合在一起的。我将把从数据库中添加和删除的函数放在哪里?我理解使用承诺,然后按照承诺行事。你在async上找不到我了。请检查我的答案,然后再试。请看你在那里做了什么。它可以工作,但我必须调用init,然后每次使用数据库时都使用数据库。不过,也许我是第一次这样做,然后在外部进行正常的调用,继续进行数据库交互。如果我将代码复制到外部文件,并在没有模块模式的情况下导入它,那么它可以正常工作,看起来很不错。但我从你的回答中学到了很多。非常感谢。可能重复的