首页 > 解决方案 > 比较 IndexedDB 中两个不同存储的值

问题描述

我有两个数据结构:

  1. 任务:taskID(自动递增)、title、status、dueDate、description
  2. 标签:tagID、tagName、tagColor、textColor、taskID

我正在尝试比较它们的 taskID 值,以便以后能够将单个任务与多个标签相关联。我编写了两个函数,getTags() 和 getTasks()。我已经设法遍历它们,获取两个商店中的所有对象,但是,我不太确定如何检查这两个值是否匹配。

function connectToDB() {
    window.webkitIndexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

    //check for support
    if(!window.indexedDB) {
        alert("Your browser do not support indexedDB. Please update you browser.")
    }

    //open database "KanbanDatabase" version 9. 
    //db = database, tx = transaction, store = store data, index = index (seach data).
    let request = window.indexedDB.open("KanbanDatabase", 9), 
        db,
        tx,
        store,
        index;

    //when creating a new databse, a store(structure) must be added
    request.onupgradeneeded = function(e) {
        let db = request.result,
        //tasks
        tasksStore = db.createObjectStore("tasksStore",{
            keyPath: "taskID", autoIncrement: true
        }),
        tasksIndex = tasksStore.createIndex("status", "status", {
            unique: false
        }),
        //tags
        tagsStore = db.createObjectStore("tagsStore", {
            keyPath: "tagID", autoIncrement: true
        }),
        tagsIndex = tagsStore.createIndex("tagID", "tagID", {
            unique: true
        });
    };

    //open database will return response. 
    //error handler:
    request.onerror = function(e) {
        console.error("There was an error opening the database: " + e.target.errorCode);
    };

    //success handler:
    request.onsuccess = function(e) {
        console.log("Successfully connected to DB")
        db = request.result;
        //tasks
        tasksTx = db.transaction("tasksStore", "readwrite");
        tasksStore = tasksTx.objectStore("tasksStore");
        tasksIndex = tasksStore.index("status");

        //tags
        tagsTx = db.transaction("tagsStore", "readwrite");
        tagsStore = tagsTx.objectStore("tagsStore");
        tagsIndex = tagsStore.index("tagID");

        db.onerror = function(e) {
            console.error("ERROR " + e.target.errorCode);
        }


        function tagsToTasks() {
            let amountOfTasks = tasksIndex.count();
            let amountOfTags = tagsIndex.count();

            function getTasks() {
                for (var i = 1; i < amountOfTasks.result+1; i++) {
                    let getTasks = tasksStore.get(i);

                    getTasks.onerror = function() {
                        console.error("There was an error looping through the tasks");
                    }

                    getTasks.onsuccess = function() {
                        console.log(getTasks.result.taskID)
                    }
                }
            }

            function getTags() {
                for (var j = 1; j < amountOfTags.result+1; j++) {
                    let getTags = tagsStore.get(j);

                    getTags.onerror = function() {
                        console.error("There was en error looping through the tags");
                    }

                    getTags.onsuccess = function() {
                        let result = getTags.result.taskID;

                        return result;
                    }
                }
            }

            function compareID() {
                //what to do?
            }

            amountOfTasks.onerror = function() {
                console.error("There was an error finding the amount of tasks");
            }

            amountOfTasks.onsuccess = function() {
                getTasks();
            }

            amountOfTags.onerror = function() {
                console.error("There was an error finding the amount of tags");
            }

            amountOfTags.onsuccess = function() {
                getTags();
            }

        }


        //fire functions
        tagsToTasks();
        listTasks();

        //close DB conection once transaction is complete.
        tasksTx.oncomplete = function() {
            db.close();
        }

        tagsTx.oncomplete = function() {
            db.close();
        }
    }
}

编辑:澄清:我需要比较两个不同商店的两个值。问题始于 tagsToTasks() 函数;如何将 getTags() 函数中的 getTags.result.taskID 返回的值与 getTasks() 函数中的 getTasks.result.taskID 进行比较?

标签: javascriptindexeddb

解决方案


第一个错误在这里。

window.webkitIndexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;` 

您将其分配给window.webkitIndexedDbwindow.indexedDb在下一行检查。

我建议使用本地 const 而不是尝试覆盖全局变量。

像这样,

const indexedDb = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

if (!indexedDb) return ....

接下来,您可以使用cursorgetAll方法来检索所有对象。此外,您不能从onSuccess事件处理程序返回任务,您需要从父范围为其分配一个变量。像这样,

let tasks = [];
tasksStore.getAll().onsuccess = function(event) {
   tasks = event.target.result
   attachTags(tasks);
};

function attachTags(tasks) {
  tags.openCursor().onsuccess = function(event) {
  var cursor = event.target.result;
  if (cursor) {
    const task = tasks.find(t => t.taskId == cursor.value.taskId);
    if (!task.tags) task.tags = []
       task.tags.push(cursor.value) ;
    cursor.continue();
  }
  else {
    return;
  }
};
}

看起来你必须经历回调地狱才能做到这一点。我正在使用该方法使用atfind指向的当前标记的 taskId 来选择任务,然后为该任务创建一个标记数组并将标记推入其中。查看您的数据模型,我假设您希望通过 taskId 外键将每个标签与相关任务相关联。cursorcursor.value

您设置事物的方式的问题在于 indexedDB 使用回调来返回值,而您的代码中没有任何地方保存这些值并将其传递给需要它们的函数。您编写的回调基本上对它们收到的值没有任何作用。您不能从回调中返回值,因为回调是由 API 调用的,而不是您的代码。您需要在回调外部为变量赋值或在回调内部进行处理。回调彼此异步执行,因此无法保证您的代码将按照您编写的顺序执行,这让您别无选择,只能从当前回调设置下一个回调,这被称为回调地狱. Promise 有助于缓解这种情况,所以如果你打算在生产中使用它, https://github.com/jakearchibald/idb公开了一个更可用的 Api。


推荐阅读