使用光标循环将JS对象添加到数组中

3
我正在尝试使用IndexedDB重新创建一个我的MySQL/PHP项目(一个存储书签、带有重点颜色、文件夹和快速拨号/固定部分的“新标签页”样式页面),作为客户端存储解决方案(希望将其移动到Chrome扩展程序)。虽然我认为我对JS有足够好的理解,但我无法弄清楚为什么以下代码只返回一个空数组。从我的观察中可以看出,“response”数组在函数开始时已经声明,因此应该可以被其中的子函数访问。插入控制台日志表明,数组已成功地被推送到迭代游标所创建的对象,但是一旦游标完成,response就变为空白。
// Specify index and key value OR omit for all
function getItems(ind,key) {
var response = [];
var transaction = db.transaction(["items"],"readonly");
var store = transaction.objectStore("items");

// If args are omitted - grab all items
if(!ind | !key) {
    var cursor = store.openCursor();
    cursor.onsuccess = function(e) {
        var res = e.target.result;
        if(res) {
            var r = {
                "name": res.value['name'],
                "url": res.value['url'],
                "folder": res.value['folder'],
                "colour": res.value['colour'],
                "dial": res.value['dial'],
                "order": res.value['order']
            };
            response.push(r);
            res.continue();
        }
        return response;
    }
} else {
    // If both args are specified query specified index
    store = store.index(ind);
    var range = IDBKeyRange.bound(key, key);
    store.openCursor(range).onsuccess = function(e) {
        var res = e.target.result;
        if(res) {
            var r = {
                "name": res.value['name'],
                "url": res.value['url'],
                "folder": res.value['folder'],
                "colour": res.value['colour'],
                "dial": res.value['dial'],
                "order": res.value['order']
            };
            response.push(r);
            res.continue();
        }
        return response;
    }
}
}

我在这里是否有些愚蠢,漏掉了什么重要的东西吗?
1个回答

3

当你编写代码时:

cursor.onsuccess = function(e) {
    ...
    return response;
}

您正在从匿名事件处理程序中返回一个值(将被忽略)。在此处理程序执行时,调用 getItems()本身早已完成。您不能简单地 return 由光标迭代等异步操作产生的值。

请尝试使用以下方式:

function getItems(callback, ind, key) {
  var response = [];
  var transaction = db.transaction(["items"],"readonly");
  var store = transaction.objectStore("items");
  transaction.oncomplete = function() { callback(response); };

  ...
}

并将其称为:

getItems(function(response) {
  for (var i = 0; i < response.length; ++i) {
    console.log(response[i]);
  }
} /* ind, key */);

啊,我明白了。我还停留在同步思维模式中。我没有考虑到onsuccess函数将返回到空值,并且很可能是在函数完成后。虽然我欣赏这种方法的工作方式,但是否有更清晰的方法让我查询我的IndexedDB存储,使其可重用和可变,最好输出到对象数组? - Dean Kellham
不是真的 @DeanKellham,这就是异步代码的工作方式。许多人认为这是一种清晰的方式。 - Josh
JavaScript 的未来版本将通过 async/await 关键字更加紧密地集成异步支持,我们正在考虑添加对 IndexedDB 的支持,以使其与这些功能更好地配合使用。 - Joshua Bell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接