Firefox 4:IndexedDB 初体验

Web 开发者已经可以使用 localStorage 来进行简单的键值对存储。但对于许多需要结构化存储和索引数据的 Web 应用来说,这还不够。Mozilla 正在开发一个名为 IndexedDB 的结构化存储 API,它支持索引。我们将在未来几周内发布一些测试版本。这可以与 WebDatabase API 相比较,WebDatabase API 由多个浏览器实现,它使用 SQLite 的一个子集。Mozilla 选择不为 多种原因,这篇文章对此进行了讨论 实现 WebDatabase。

为了比较 IndexedDB 和 WebDatabase,我们将展示四个示例,这些示例使用每个规范中大部分异步 API。阅读这些示例后,SQL 存储使用表格(WebDatabase)和 JavaScript 对象存储使用索引(IndexedDB)之间的差异会变得很明显。这些 API 的同步版本仅在 worker 线程上可用。由于并非所有浏览器都实现了 worker 线程,因此此时不会讨论同步 API。IndexedDB 代码基于 Mozilla 提交给 W3C WebApps 工作组的提案,该提案目前已获得积极反馈。这两个 API 的代码不包含任何错误处理(为了简洁),但生产代码应始终包含错误处理!

这些示例用于存储糖果店销售糖果给顾客(我们称之为孩子)的情况。candySales 中的每个条目代表向一个孩子销售一定数量的糖果,该孩子由 candykids 中的相应条目指定。

示例 1 - 打开和设置数据库

第一个示例演示了如何打开数据库连接以及在版本号不正确的情况下创建表格或对象存储。打开数据库后,两个示例都会检查版本并创建必要的表格或对象存储,然后设置正确的版本号。WebDatabase 在处理版本方面更加严格,如果数据库版本不是调用者期望的版本(由传入 openDatabase 的第二个参数指定),它会抛出错误。IndexedDB 允许调用者根据需要处理版本控制。请注意,工作组正在积极讨论 IndexedDB 如何处理版本更改

WebDatabase

var db = window.openDatabase("CandyDB", "",
                             "My candy store database",
                             1024);
if (db.version != "1") {
  db.changeVersion(db.version, "1", function(tx) {
    // User's first visit.  Initialize database.
    var tables = [
      { name: "kids", columns: ["id INTEGER PRIMARY KEY",
                                "name TEXT"]},
      { name: "candy", columns: ["id INTEGER PRIMARY KEY",
                                 "name TEXT"]},
      { name: "candySales", columns: ["kidId INTEGER",
                                      "candyId INTEGER",
                                      "date TEXT"]}
    ];

    for (var index = 0; index < tables.length; index++) {
      var table = tables[index];
      tx.executeSql("CREATE TABLE " + table.name + "(" +
                    table.columns.join(", ") + ");");
    }
  }, null, function() { loadData(db); });
}
else {
  // User has been here before, no initialization required.
  loadData(db);
}

IndexedDB

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var db = event.result;
  if (db.version != "1") {
    // User's first visit, initialize database.
    var createdObjectStoreCount = 0;
    var objectStores = [
      { name: "kids", keyPath: "id", autoIncrement: true },
      { name: "candy", keyPath: "id", autoIncrement: true },
      { name: "candySales", keyPath: "", autoIncrement: true }
    ];

    function objectStoreCreated(event) {
      if (++createdObjectStoreCount == objectStores.length) {
        db.setVersion("1").onsuccess = function(event) {
          loadData(db);
        };
      }
    }

    for (var index = 0; index < objectStores.length; index++) {
      var params = objectStores[index];
      request = db.createObjectStore(params.name, params.keyPath,
                                     params.autoIncrement);
      request.onsuccess = objectStoreCreated;
    }
  }
  else {
    // User has been here before, no initialization required.
    loadData(db);
  }
};

示例 2 - 将孩子存储到数据库

此示例将多个孩子存储到相应的表格或对象存储中。此示例演示了使用 WebDatabase 时必须处理的一种风险:SQL 注入攻击。在 WebDatabase 中,必须使用显式事务,但在 IndexedDB 中,如果只访问一个对象存储,则会自动提供事务。IndexedDB 中的事务锁定是针对每个对象存储的。此外,IndexedDB 使用 JavaScript 对象进行插入,而 WebDatabase 要求调用者绑定特定的列。在这两种情况下,您都会在回调函数中获得插入 ID。

WebDatabase

var kids = [
  { name: "Anna" },
  { name: "Betty" },
  { name: "Christine" }
];

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.transaction(function(tx) {
  for (var index = 0; index < kids.length; index++) {
    var kid = kids[index];
    tx.executeSql("INSERT INTO kids (name) VALUES (:name);", [kid],
                  function(tx, results) {
      document.getElementById("display").textContent =
          "Saved record for " + kid.name +
          " with id " + results.insertId;
    });
  }
});

IndexedDB

var kids = [
  { name: "Anna" },
  { name: "Betty" },
  { name: "Christine" }
];

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var objectStore = event.result.objectStore("kids");
  for (var index = 0; index < kids.length; index++) {
    var kid = kids[index];
    objectStore.add(kid).onsuccess = function(event) {
      document.getElementById("display").textContent =
        "Saved record for " + kid.name + " with id " + event.result;
    };
  }
};

示例 3 - 列出所有孩子

此示例列出了存储在 kids 表或 kids 对象存储中的所有孩子。WebDatabase 使用结果集对象,该对象将在所有行都检索完成后传递给提供的回调方法。另一方面,IndexedDB 在检索到结果时会将游标传递给事件处理程序。因此,结果应该返回得更快。虽然本示例中没有展示,但您也可以通过简单地不调用 cursor.continue() 来停止使用 IndexedDB 迭代数据。

WebDatabase

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.readTransaction(function(tx) {
  // Enumerate the entire table.
  tx.executeSql("SELECT * FROM kids", function(tx, results) {
    var rows = results.rows;
    for (var index = 0; index < rows.length; index++) {
      var item = rows.item(index);
      var element = document.createElement("div");
      element.textContent = item.name;
      document.getElementById("kidList").appendChild(element);
    }
  });
});

IndexedDB

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  // Enumerate the entire object store.
  request = event.result.objectStore("kids").openCursor();
  request.onsuccess = function(event) {
    var cursor = event.result;
    // If cursor is null then we've completed the enumeration.
    if (!cursor) {
      return;
    }
    var element = document.createElement("div");
    element.textContent = cursor.value.name;
    document.getElementById("kidList").appendChild(element);
    cursor.continue();
  };
};

示例 4 - 列出购买过糖果的孩子

此示例列出了所有孩子以及每个孩子购买了多少糖果。WebDatabase 只需使用 LEFT JOIN 查询,使此示例非常简单。IndexedDB 目前没有为在不同对象存储之间执行连接指定的 API。因此,此示例打开一个指向 kids 对象存储的游标和一个指向 candySales 对象存储上的 kidId 索引的对象游标,并手动执行连接。

WebDatabase

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.readTransaction(function(tx) {
  tx.executeSql("SELECT name, COUNT(candySales.kidId) " +
                "FROM kids " +
                "LEFT JOIN candySales " +
                "ON kids.id = candySales.kidId " +
                "GROUP BY kids.id;",
                function(tx, results) {
    var display = document.getElementById("purchaseList");
    var rows = results.rows;
    for (var index = 0; index < rows.length; index++) {
      var item = rows.item(index);
      display.textContent += ", " + item.name + "bought " +
                             item.count + "pieces";
    }
  });
});

IndexedDB

candyEaters = [];
function displayCandyEaters(event) {
  var display = document.getElementById("purchaseList");
  for (var i in candyEaters) {
    display.textContent += ", " + candyEaters[i].name + "bought " +
                           candyEaters[i].count + "pieces";
  }
};

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var db = event.result;
  var transaction = db.transaction(["kids", "candySales"]);
  transaction.oncomplete = displayCandyEaters;

  var kidCursor;
  var saleCursor;
  var salesLoaded = false;
  var count;

  var kidsStore = transaction.objectStore("kids");
  kidsStore.openCursor().onsuccess = function(event) {
    kidCursor = event.result;
    count = 0;
    attemptWalk();
  }
  var salesStore = transaction.objectStore("candySales");
  var kidIndex = salesStore.index("kidId");
  kidIndex.openObjectCursor().onsuccess = function(event) {
    saleCursor = event.result;
    salesLoaded = true;
    attemptWalk();
  }
  function attemptWalk() {
    if (!kidCursor || !salesLoaded)
      return;

    if (saleCursor && kidCursor.value.id == saleCursor.kidId) {
      count++;
      saleCursor.continue();
    }
    else {
      candyEaters.push({ name: kidCursor.value.name, count: count });
      kidCursor.continue();
    }
  }
}

总的来说,IndexedDB 简化了与数据库交互的编程模型,并允许使用大量用例。工作组正在设计这个 API,以便它可以被 JavaScript 库包装;例如,在我们的 IndexedDB 实现之上有很多空间可以构建 CouchDB 样式的 API。在 IndexedDB 之上构建基于 SQL 的 API(例如 WebDatabase)也是非常可能的。Mozilla 渴望获得开发人员对 IndexedDB 的反馈,尤其是因为规范尚未最终确定。欢迎在这里留下评论,表达您的想法,或通过 Rypple 留下匿名反馈

关于 Arun Ranganathan

Arun Ranganathan 的更多文章...

关于 Shawn Wilsher

Shawn Wilsher 的更多文章...


182 评论

  1. HurfDurf

    你们还会添加一个选项来禁用这个“功能”吗?

    没有人希望有更多类型的隐形 Cookie。

    2010 年 6 月 1 日 下午 12:30

    1. Shawn Wilsher

      您可以像禁用 sessionStorage 或 localStorage 一样禁用它。

      2010 年 6 月 1 日 下午 1:25

      1. Andy

        > 没有人希望有更多类型的隐形 Cookie。

        您听说过支持离线功能的 Web 应用吗?这正是 IndexedDB 的主要用途。

        友善的建议:*思考*,然后再发布。

        2010 年 6 月 1 日 下午 2:35

        1. Shawn Wilsher

          请保持文明讨论。

          2010 年 6 月 1 日 下午 8:13

          1. Ege

            保持文明是一回事,但现在大多数人已经厌倦了这种过度谨慎的回应。您希望有人尊重内容并提出有意义的问题。那个问题不是一个好例子。您解释了一种技术,第一个评论者询问如何禁用它……我们怎么能保持文明呢?我完全同意 Andy 的观点。在说些什么之前,您需要“思考”。就像您面对面交谈时那样。

            2010 年 8 月 26 日 上午 7:18

  2. […] 新文章 […]

    2010 年 6 月 1 日 下午 1:24

  3. Jesper Kristensen

    那个示例代码真的很丑陋。

    不仅像新的附加组件管理器 API 这样的 Mozilla 内部 API 几乎不可用,现在它还感染了开放标准。

    浏览器厂商真的需要推动 JavaScript 向前发展,并提供一种编写异步 JavaScript 的合理方法。

    2010 年 6 月 1 日 下午 1:44

    1. Preston L. Bannister

      同意。作为 JavaScript 使用示例和从 JS 使用的 API,这是一些非常丑陋的代码。

      2010 年 6 月 2 日 下午 1:51

  4. Wes Brown

    你让我信服了,直到看到 JOIN 示例……那简直是噩梦。在出现一些合理的 API 用于多表访问之前,没有人愿意为了执行一个简单的连接而经历所有这些容易出错的繁文缛节。

    2010 年 6 月 1 日 下午 2:00

    1. Shawn Wilsher

      没错,在当前的 API 提案中,连接并不那么令人愉快。但是,IndexedDB 更像是一个文档存储而不是一个关系数据库,如果您将对象存储映射到表格,就像我们在这个示例中所做的那样,您最终将不得不担心连接。如果您 将此考虑得更像一个 CouchDB 样式的数据库,事情会变得更容易使用

      2010 年 6 月 1 日 下午 2:19

      1. voracity

        如果您在基础 API 中没有提供简单的连接函数,那么您就有风险,没有人会尝试长时间地去理解 IndexedDB 的思维方式,以便费心在顶部编写一个更简单的 API,其中包含我们真正想要的:即连接!

        一个简单的连接函数应该非常容易实现,所以为什么不直接实现呢?嵌套对象很棒,事实上非常棒,但它们可能无法涵盖人们想要使用连接的甚至一半的情况;连接更像是交叉引用文档,而不是文档中的子部分。(并且那篇 CouchDB 连接文章显示了事情会变得多么难以理解。)

        我认为总体方法和推理很好。只需使用连接来连接它。

        2010 年 6 月 2 日 下午 07:29

    2. Tom Harrison

      我曾经持怀疑态度,但正如您所说,直到看到连接示例后我才接受。

      IndexDB 只是一个哈希表,从概念上来说很简单,速度很快,而且功能强大,但作为一种存储和检索结构化数据的机制,它只在非常有限的情况下有用。它适合处理序列化对象。

      现实存储中一个重要的用例是移动应用程序,这些应用程序应该能够在没有连接的情况下工作。将服务器端数据库的一个子集存储在本地,然后在下一次连接时同步是有意义的。

      我并不喜欢 SQL(我目睹了所谓的开发人员多年来滥用它),但它是一个经过良好开发的标准,解决了哈希数据库无法解决的许多问题。缺乏标准是放弃这种方法的可笑理由,而经典的臃肿心态则建议我们在 IndexedDB 存储引擎之上构建另一个 SQL 引擎。SQLite 很好。

      抱歉,我正在发泄。

      2010 年 8 月 19 日 下午 12:24

      1. Artifex

        我必须同意,IndexedDB 的代码对我来说远不如 Web 数据库代码吸引人。我是一名 Web 开发人员,与大多数 SQL 工作隔离开来,所以我认为像 IndexedDB 这样的方法对我来说更有吸引力,因为它更熟悉,但我必须在这里使用标准的 SQL 查询语言。我不是数据库管理员,但那个 SQL 代码看起来更有吸引力得多。

        2010 年 12 月 1 日 下午 14:34

  5. George Moschovitis

    异步 JavaScript 的有趣习语。

    顺便问一下,您可以在单个“查询”中使用多个索引吗?
    是否可以执行 >、< 查询?

    2010 年 6 月 1 日 下午 14:40

    1. Shawn Wilsher

      我认为当前的提案不允许每个查询使用多个索引。它支持闭合范围(我认为您使用“>、<”和 IDBKeyRange 接口询问的就是这个)。

      interface IDBKeyRange {
        const unsigned short SINGLE = 0;
        const unsigned short LEFT_OPEN = 1;
        const unsigned short RIGHT_OPEN = 2;
        const unsigned short LEFT_BOUND = 4;
        const unsigned short RIGHT_BOUND = 8;
      
        readonly attribute any left;
        readonly attribute any right;
        readonly attribute unsigned short flags;
      };
      
      2010 年 6 月 1 日 下午 14:53

  6. John

    我认为您在 JavaScript 风格方面失去的,在可读性方面您在 SQL 示例中获得了。我必须努力才能理解您在 IndexedDB 示例中所做的事情(因为尽管它可能更接近 JavaScript 的本质,但对我们来说是新的)。几乎每个人都知道 SQL,所以阅读起来很简单。

    另外,只是一个问题,因为我真的很在意,当您说

    var request = window.indexedDB.open(“CandyDB”,
    “My candy store database”);

    然后在下一行定义 onsuccess 处理程序时,是否存在竞争条件?现在,这可能永远不会成为问题,但这种情况不是正在发生吗?

    2010 年 6 月 1 日 下午 15:26

    1. Shawn Wilsher

      关于您的第一个观点,我将将您引导至 Arun 的文章,他在文章中谈到了我们为什么没有使用 SQL。

      那里不存在竞争条件,因为 JavaScript 将始终运行至完成。也就是说,您的整个函数将在任何回调或事件处理程序可能开始之前运行。我们甚至不会尝试在您的函数完成之前调度成功。

      2010 年 6 月 1 日 下午 16:26

  7. Laurens Holst

    如果不会立即被否决,我建议使用 RDF 作为一种更高效、定义明确的以图形为导向的数据建模技术。

    2010 年 6 月 1 日 下午 15:27

    1. goldfrapper

      Mozilla 过去使用过 RDF。考虑到 Web 应用程序的资源丰富性,适当的/可接口的 RDF 实现确实会更好。或者他们当然可以采用类似 CouchDB 的模型。

      2010 年 6 月 2 日 上午 01:19

      1. Shawn Wilsher

        IndexedDB 非常类似于 CouchDB 模型。CouchDB 也可以在它之上实现(我们正在与 CouchIO 团队合作,以确保它可以实现)。

        2010 年 6 月 2 日 上午 09:55

  8. Screwtape

    看到又一个异步 API,它不能与网页中可用于 JS 的所有其他异步 API(例如 XmlHttpRequest、Web Workers、setTimeout 等等)组合使用,这让我感到难过。我见过的最好的异步结果模型是 Twisted Python 的“Deferred”类,它已作为 MochiKit 框架的一部分被整齐地移植到 JavaScript 中。

    http://www.mochikit.com/doc/html/MochiKit/Async.html#fn-deferred

    在同一个 API 中查看 DeferredLock 和 DeferredList,以获取可与使用 Deferred 的任何其他异步请求轻松组合的有用功能。

    2010 年 6 月 1 日 下午 16:55

    1. Shawn Wilsher

      它究竟如何不能与 XMLHttpRequest 组合使用?我们对反馈感兴趣,但我不明白为什么它不能组合使用,因为它与 XMLHttpReqeust 使用相同的事件模型。

      2010 年 6 月 1 日 下午 17:01

      1. Screwtape

        我所说的“可组合”并不仅仅意味着“可以与之协同工作”,而是意味着“自然地与之并列”。XMLHttpRequest 和 IndexedDB 都使用“事件模型”,但它们使用不同的事件(“onreadystatechange” 与“onsuccess” 和“onerror”)。

        假设我有一些代码当前使用 XMLHttpRequest 检索各种数据,我想更新它,以便它首先检查 IndexedDB 缓存,然后再发送请求。如果我想在不更改所有调用它的代码的情况下实现此缓存,我的新代码必须完成所有 IndexedDB 操作,然后返回一个模拟(有点复杂)XMLHttpRequest API 的对象。

        使用 Deferreds,该 shim 函数可能看起来像这样

        function getDataShim(key) {
            var d = getDataFromDB(key);
        
            function cacheAndPassthrough(result) {
        	d = cacheValueInDB(result);
        	d.addCallback(function (ignored) { return result; });
        	return d;
            }
        
            function notFoundInDB(failure) {
        	var d = getDataFromWeb(key);
        
        	d.addCallback(cacheAndPassthrough);
        
        	return d;
            }
        
            d.addErrback(notFoundInDB);
        
            return d;
        }
        

        大致翻译过来,这意味着“尝试从数据库中获取数据。如果数据存在,则它是结果。如果遇到错误(例如“未找到”),则尝试从 Web 上获取数据。如果我们从 Web 上获取数据成功,则将找到的值缓存到数据库中并返回该数据。如果我们无法从 Web 上获取数据,或者无法缓存数据,则返回该错误。

        我会第一个承认,Deferreds 并不能生成最干净、最易读的代码,但在过程语言中,异步函数永远不会干净整洁 - 而且 Deferreds 比每个异步函数都使用自己的方式来返回结果和发出错误信号要好得多。

        2010 年 6 月 1 日 下午 19:54

        1. Shawn Wilsher

          我不确定我是否完全同意您关于异步 API 和过程语言的观点。生成器 在很大程度上使代码变得非常易读,正如这里所演示的那样

          W3C 中现在还有另一个规范(我认为它类似于可编程缓存),它实现了您所谈论的许多功能。

          2010 年 6 月 1 日 下午 20:18

          1. Screwtape

            你说得对,基于生成器的代码确实使异步特性看起来平坦得多 - 我怀疑如果您的基于生成器的异步函数想要调用其他基于生成器的异步函数,它会变得更加难看。

            Twisted 有几种方法可以将 Python 的生成器(与您所说的 JS 生成器非常类似)与它的 Deferred 系统集成在一起。

            http://blog.mekk.waw.pl/archives/14-Twisted-inlineCallbacks-and-deferredGenerator.html

            我并不特别感兴趣缓存系统,那只是我想出的第一个将多个不同异步事件组合在一起的例子。

            2010 年 6 月 1 日 下午 22:41

          2. ged

            我认为就是这个

            http://www.w3.org/TR/DataCache/

            2010 年 10 月 21 日 下午 12:32

  9. Music Teacher

    这很有趣!是的,虽然 JOIN 的内容可能有点笨拙,但我不得不说我很高兴您避免使用 SQL 数据库功能。

    2010 年 6 月 1 日 下午 16:59

  10. Jonas Sicking

    就我而言,我同意那些呼吁在 JavaScript 中使用更好方法进行异步编码的人。除了前面提到的 Twisted Python 中的“Deferred”类之外,Dojo 也有类似的 Deferred 模块,并且 Firefox 的最新版本有一个实验性的浅层延续实现(请参见https://mdn.org.cn/en/Core_JavaScript_1.5_Guide/Iterators_and_Generators)。

    我很乐意看到各种异步 DOM API 能够为其中一项功能提供原生支持。但是,试图在数据库规范中指定要使用的模型将是一个错误。这可能会导致灾难性的结果,例如 XMLHttpRequest 使用一个 Defer 解决方案,而 IndexedDB 使用另一个解决方案。

    我很乐意看到为 Web 开发的异步 API 解决方案。然后,我们可以在许多规范中添加对它的支持,例如 IndexedDB、Web Workers、XMLHttpRequest、WebSocket 等等。但是,在我们拥有这样的标准化解决方案之前,我认为最好坚持现有的模型,即 DOM 事件。这样,像 dojo.Deferred 这样的库就有了一个一致的 API 来处理,以弥合差距,直到我们拥有更好的东西。

    关于联接。是否要在我们的示例中包含联接是一个艰难的决定。正确使用 IndexedDB 的方法是将孩子列表和销售数据都放到一个表中。例如,使用以下类型的对象:

    { name: "Anna", sales: [
      { date: "5-1-2010", candyType: "lollipop" },
      { date: "5-13-2010", candyType: "swedish fish"}]
    }
    

    这完全消除了对联接的需求,并使操作变得非常容易。

    你仍然可以创建一个仅包含销售数据的索引,以便在需要以这种方式进行查询时使用。

    因此,实际上,对象存储与自定义索引相结合,消除了对联接的大部分需求。我们之所以仍在示例中包含联接,是因为我们想展示一个复杂查询的示例,以激发你的想象力。

    2010 年 6 月 1 日 下午 6:48

  11. David

    我很高兴你推动 IndexedDB 的发展。虽然从一开始看起来 IndexedDB 比较难用,但这就是框架的作用所在。拥有一个低级 API,你可以用它来构建一个用户友好的数据库 API(无论是基于 SQL 的还是其他类型的),比从一个用户友好的 API 开始,但却缺乏灵活性要合理得多。

    顺便说一下,电子邮件地址验证器拒绝了合法的电子邮件地址。(例如,user+something@example.com 不起作用)

    2010 年 6 月 1 日 下午 6:53

    1. Shawn Wilsher

      工作组的目标也是如此。我们正在尝试创建一个低级 API,它功能强大,以便库可以利用它做一些惊人的事情。到目前为止,这种方法在 web 上取得了很好的效果,一些非常好的 API 后来被标准化,并被浏览器供应商优化了速度。

      2010 年 6 月 1 日 晚上 8:26

    2. Tom Harrison

      听起来,IndexedDB 的做法是创建一个存储引擎,然后放弃了一种成熟且功能强大的数据管理方法。

      人们不喜欢 SQL 的原因是它解决了一个根本上非常困难的问题,特别是强制数据完整性。我已经花了许多年时间清理不良数据,我知道这是一个很难的问题。许多数据库都做错了,有些还错得很离谱。SQL 很困难,但从某种意义上说,它仍然是一个对非常困难问题的优雅解决方案。据我所知,IndexedDB 并没有解决这个问题,而这将是一个严重的损失。

      2010 年 8 月 19 日 下午 12:36

  12. Mark Rendle

    “IndexedDB 通常简化了与数据库交互的编程模型。”

    它显然没有。与数据库交互的编程模型包含联接。也许同步模型更好,但异步 JavaScript 看起来很糟糕。

    2010 年 6 月 2 日 上午 1:44

  13. alex

    规范的黄金法则:简单的事情应该简单,复杂的事情应该可行。

    在 IndexedDB 中,即使是最简单的事情也极其复杂。我同意,SQL 语法可能不应该在 web 应用程序中使用,但它*应该*是定义纯 JS 查询的更好的方式,而无需编写数百行代码来执行简单的联接。

    我的结论:IndexedDB 目前还没有准备好用于任何生产环境。

    2010 年 6 月 2 日 晚上 10:05

  14. 29a

    在我看来,它比 WebDB 好。API 似乎有点冗长,但应该很容易在它之上构建类似于 mongoose 的东西:http://www.learnboost.com/mongoose/.

    Jonas

    2010 年 6 月 3 日 上午 8:37

  15. Darren

    Shawn,
    正如这位先生指出的那样,你的代码中存在一个竞争条件。你在一行语句中打开 IndexedDB,然后在下一行语句中尝试添加回调处理程序。如果第一个调用完成并且数据库打开完成,而在添加 onsuccess 处理程序之前,则该处理程序永远不会被调用。

    另一方面,如果数据库打开调用在调用 onsuccess 处理程序之前没有完成,那么为什么不呢?正确的方法是在调用该方法的同时添加回调,这样在内部,处理程序会在尝试打开数据库之前添加。

    请更正此问题!:)

    Darren

    2010 年 6 月 4 日 上午 11:00

    1. Shawn Wilsher

      实际上,这段代码中不存在竞争条件,正如我在这里指出的那样。JavaScript 是单线程的,因此你的异步回调只有在你当前的代码执行完毕后才会发生。如果有需要,我乐意详细说明,但这对于实现者来说,确保消费者不会出现竞争情况是相当简单的。

      如果你在 setTimeout 中添加事件侦听器,就会出现竞争条件。

      2010 年 6 月 7 日 上午 10:16

      1. Darren Govoni

        我并不信服,我认为为了让其他人感到舒适,你应该更详细地解释一下。但我会解释为什么我认为存在竞争条件。

        1:        var request = window.indexedDB.open("CandyDB",
                                            "My candy store database");
        2:        request.onsuccess = function(event) {
        
                   };
        

        在上面的代码(单线程)中,语句 1 完成后,语句 2 才开始。正确吗?当语句 1 完成时,数据库可能已经打开了。通常,所有注册的侦听器都会在语句 1 完成之前被通知,这就是如何避免竞争条件的。因此,这是确定的。

        然而,第 2 行现在尝试添加一个侦听器。那么,什么代码将在第 2 行中通知侦听器打开事件,以及执行该操作的代码位于第 1 行的完成范围之外。没错吧?

        2010 年 6 月 7 日 上午 10:33

        1. Shawn Wilsher

          我认为你假设 openDatabase 是同步的,但它实际上是异步的。在 openDatabase 返回之后,才会在一段时间后才分发事件。我将撰写一篇新的帖子,处理一些最常问的问题,并提供详细的答案,其中我会提供更详细的响应。

          2010 年 6 月 7 日 上午 10:42

  16. Mewp

    看起来这是一个问题,我们更喜欢 CouchDB 式的数据库还是 SQL 式的数据库。

    文章作者认为,我们可以在 IndexedDB 之上实现这两种数据库,但这对于任何其他数据库 API 来说也是如此。我们也可以在 WebDatabase 之上实现 IndexedDB。我们甚至可以在本地存储之上实现 WebDatabase,所以呢?

    这些实现将比原生机制慢,因此,我认为浏览器应该实现更快、更灵活的机制。

    关于用适当的数据库结构来替换联接,有些情况下联接仍然是必要的。例如,一个应用程序可能有一个时间表,或者某种日历。我们想要检查是否有两个事件同时发生。

    在 SQL 中:SELECT 1 FROM Timetable t1 JOIN Timetable t2 ON t1.time = t2.time LIMIT 1

    在 IndexedDB 中(只是猜测,如果我错了请纠正我)
    var rows = [];
    var t1 = transaction.objectStore(‘Timetable’);
    t1.openCursor().onsuccess = function(e) {
    var c1 = c.result;
    var t2 = transaction.objectStore(‘Timetable’);
    t2.onsuccess = function(e) {
    var c2 = c.result;
    if(c1.time == c2.time) {
    rows.push(1);
    // 现在我们如何在这里结束计算,因为我们已经发现存在这样的事件?
    }
    }
    c1.continue();
    }

    即使不考虑代码复杂性,如果以原生方式实现,哪一个会更快?我的猜测是 SQL。

    2010 年 6 月 4 日 下午 1:46

    1. Shawn Wilsher

      IndexedDB 本质上只是公开了一个 B 树 API。CouchDB 和基于 SQL 的数据库都是基于 B 树实现的。IndexedDB 实际上是最小的公分母。负责规范的工作组的设计目标是使其足够简单,以便人们可以在没有库的情况下使用它,但完全期望库会层出不穷,并解决原始 B 树 API 的许多痛点。

      至于性能,你的论点并不适用。磁盘 I/O 将远远慢于 JavaScript 解析数据。即使这样,现代浏览器中的 JavaScript 引擎也并不慢。

      2010 年 6 月 7 日 上午 10:27

  17. Martin

    我有点惊讶,在示例 4 中,有人认为 IndexedDB 简化了生活。
    SQL 方法简单明了。
    而且在大多数情况下,SQL 已经存在。

    2010 年 6 月 7 日 上午 3:52

    1. Shawn Wilsher

      我将引用我最初在这里写的内容……

      WebDatabase 只是使用了一个 LEFT JOIN 查询,这使得这个示例变得非常简单。IndexedDB 目前还没有为在不同对象存储之间执行联接指定 API。

      2010 年 6 月 7 日 上午 10:32

  18. Darren Govoni

    “我认为你假设 openDatabase 是同步的,但它实际上是异步的。”

    Shawn,这就是为什么它是竞争条件的原因。也许在你的测试中,打开数据库所花费的时间总是发生在 result.onsuccess 注册之后,但你不能期望这种行为始终如一。从计算的角度来看,它是不确定的。

    为了使其在计算上可靠且确定,处理程序必须在 open 调用之前注册,或者应该抛出异常。在我看来,赌博一个调用*应该*在另一个独立的异步调用被调用之前完成会导致问题。只是我的一点微不足道的想法。

    2010 年 6 月 7 日 上午 11:26

    1. Rob Arnold

      “从计算的角度来看,它是不确定的。”

      确实,打开数据库实际上是不确定的,但数据库已打开的通知是确定的。通知必须根据规范在主线程上分发;这是创建请求的代码正在运行的线程。由于 JavaScript 具有运行至完成的语义,正如 Shawn 早些时候提到的那样,通知只有在创建请求的 JS 代码完成之后才会分发——这包括语句 2 和任何未来的语句,直到控制流返回到事件循环。因此,在你标注的示例中,通知不可能在语句 2 之前分发,即使数据库实际上在那之前已经打开了。明白了吗?

      2010 年 6 月 7 日 下午 12:03

  19. austin

    你仍然没有理解他的意思,只有在脚本退出后才会进行打开数据库的调用。因此,如果我在这两条语句之间计算从 1 到 10 亿的素数之和,我们仍然不会出现问题,因为直到我完成计算,打开数据库的调用才会发生。一旦完成,就会调用数据库,并发送通知。

    2010 年 6 月 10 日 上午 9:24

  20. Darren Govoni

    因此,如果我使用 FireBug 单步执行代码,打开数据库调用中的所有代码都会完成,并且不会阻塞。没错吧?然后函数在主线程中完成。没错吧?好的,那么发出通知的代码是什么?你说执行现在回到一些以前的代码来完成?我不这么认为。

    代码在哪里?回到打开数据库的方法中?那么你说在打开数据库方法之后,没有副作用?从编程的角度来看,这完全是胡说八道。但我只会等待代码,然后自己单步执行它。

    2010 年 6 月 11 日 上午 04:53

    1. Rob Arnold

      “所以,如果我使用 FireBug 步进代码,数据库打开调用中的所有代码都将完成并且不会阻塞。对吗?”

      是的。

      “那么函数在主线程中完成。对吗?”

      是的。但请注意,函数并非通过打开数据库来完成。它通过在单独的线程上下文中排队执行同步打开来完成,然后返回。

      “好的,那么什么代码会发出通知?”

      当上述同步打开在单独的线程上完成时,它会排队一些代码以在主线程的事件循环中运行。该代码将运行调用 onsuccess。

      “你是在说执行现在返回到一些之前的代码来完成?我不这么认为。”

      嗯,我不确定你为什么认为 open() 不像普通函数一样返回。它确实返回了,但不能保证它返回时数据库已经打开。如果数据库在它返回时(或在它排队同步打开后的任何时间点)被打开,那么主线程的事件队列中将有一个事件等待调度通知。该事件不会在当前 JS 执行线程完成之前运行。这就是“运行至完成”语义的含义。

      “所以你的意思是,在数据库打开方法之后,没有副作用?”

      从脚本的角度来看,没有,直到它将控制权返回给它的原始调用者或以其他方式调用事件循环。

      从浏览器的角度来看,当然有一个副作用——生成新的执行线程来打开数据库。

      2010 年 6 月 11 日 上午 10:33

  21. Brett Zamir

    我很想看到一个使用 XQuery 的原生 XML 数据库,它可以被网站访问(并且有可能在应用程序之间共享)。

    我无法理解为什么除了像我这样的铁杆粉丝之外,XQuery 没有得到更广泛的采用,除了猜测这是因为在像 JavaScript 或 PHP 这样的常见且易于访问的开发环境中缺乏可访问性。

    它是一种如此优雅和表达能力强的语言,在我看来,它比其他任何语言都更适合 Web 模型。

    上面的例子显示 IndexDB 比 SQLite 的代码更长。如果人为编造的例子更长,这似乎不是一个好兆头,尽管我承认我没有仔细研究过它。但它不像 XQuery 那样吸引我,XQuery 很友好。

    Web 不应该利用现有的对 X/HTML 的理解吗?Web 的最基本单元就是建立在 X/HTML 之上的(因为 XQuery 方便地允许在输入和输出中包含目标 XML——类似于 E4X 的方式,尽管不幸的是,其他浏览器没有给予它关注),并且还基于其他已经方便、标准且熟悉的技术(因为 XQuery 利用 XPath)吗?

    这个新的 API 不应该对分层数据同样有效吗?因为大多数 Web 文档都是分层结构的?

    数据表创建者不应该能够使用简单的 XHTML 来构建一个 XHTML 表格,并且它既可以作为文档本身直接查看和编辑,也可以通过 XPath/XQuery 轻松查询吗?

    如果你想使用表格,让用户创建他们最熟悉的表格。对于那些想要能够方便地使用分层数据(其中可能包括表格)的人,包括通过对文档或文档集合进行直接查询,让我们使用它……

    我不知道它的性能如何,但已经有一个非常小的 XML 数据库(Apache 许可证),Sedna: http://modis.ispras.ru/sedna/,它可能用作基础。

    2010 年 6 月 17 日 下午 19:55

    1. Steve Antal

      XHTML 已经过时/被弃用,在我看来,我们需要大众理解的流行标准,因为 Web 开发人员需要学习的东西已经太多了。

      这就是为什么我们需要 SQL 的原因,我们需要将所需的知识量降到最低。

      例如,XUL 可能比 HTML 更适合表达 UI,但它对于创建简单的 Firefox 扩展来说是必要的,这一点很尴尬。我不想学习无数种新技术,我的客户不会为技术付费,他们为功能付费。
      为一个网站创建一个简单的浏览器扩展很好,但在这个场景中,我不想为了实现它而学习一门新的语言。

      我的例子可能很难理解,但这里有一个简化的版本(与本评论无关)
      停止发明新技术!我们不需要新技术,我们需要的是真正有效的技术。

      2010 年 6 月 17 日 下午 20:42

  22. Brett Zamir

    我的倒数第二段应该包含 table 标签,但它由于过度的评论而被删除了:<table>

    2010 年 6 月 17 日 下午 19:58

  23. Brett Zamir

    为了避免分散我刚刚提出的简化建议,我可能还要补充一点,RDF 也有一些 XQuery 风格的接口(例如,http://www.w3.org/2004/07/16-FA/http://www.fatdog.com/xsrql.html),可能对那些愿意花时间生成高度结构化数据的人(例如,参见 http://dbpedia.org/)有吸引力,但我只是建议将其作为更简单的 XQuery+XML 的补充,而不是替代品。

    为了回应刚刚的评论,XHTML 并没有消亡,因为 HTML5 本身允许 XHTML 序列化。如果你了解 HTML,那么学习如何编写 XHTML 大概只需要 5 分钟:https://w3schools.org.cn/xhtml/xhtml_html.asp。并且,基于 XQuery 的 XML 数据库可以与 HTML 配合使用并不奇怪(尤其是在 HTML5 中明确规定了解析 HTML 的规则)。

    我用我的 XqUSEme 扩展做到了这一点,它使用 Firefox 自身的 HTML 内部表示(通常非常接近 XML):https://addons.mozilla.org/en-US/firefox/addon/5515,显然,有趣的项目 XQIB 也使用 Tidy 做到了这一点:http://www.xqib.org/。但是,它们目前都没有与 XML 数据库(仅单个文档)配合使用。

    关于查询语言,SQL 更为熟悉(即使不完全是标准),这是事实,如果我说了算,我甚至会提倡使用它。但是 SQL 并不适合处理分层数据,而 XML+XQuery 却可以。在我看来,SQL 的成功是历史的偶然,如果 XQuery(SQL 的共同创造者本人也参与其中)是第一个出现的,它就会取代 SQL。我希望下一代能够接触到它的直观性和强大功能,尤其是在结合全文本和更新功能的情况下。

    这里有一些针对维基百科数据库(使用我提到的非常有趣的 Sedna XML 数据库)使用 XQuery 的有趣用例:http://wikixmldb.org/help/use-cases

    2010 年 6 月 17 日 下午 21:03

  24. Andrzej Lis

    很容易理解那些只能够想象表格的开发人员。但 Web 是一个关于分层组织的数据(域和文档)的图,我在那里看不到任何表格。我欢迎更适合半结构化信息的存储。那么我的问题是,以原生 XML 数据库 http://exist-db.org 的出色例子为例,在 IndexedDB 中实现一些 XML 索引方案(http://atomic.exist-db.org/articles/wolfgangs_talk.pdf)有多容易?

    2010 年 6 月 21 日 上午 11:34

  25. Andrzej Lis

    很容易理解那些只能够想象表格的开发人员。但 Web 是一个关于分层组织的(域和文档)信息的图。我欢迎更适合 Web 数据的半结构化性质的存储。
    我的问题是,以原生 XML 数据库 http://exist-db.org 的出色例子为例,

    在 IndexedDB 中实现一些 XML 索引方案有多容易?

    (为了在不搜索的情况下了解关系,而只需比较节点标识符,这对 XQuery 等很有用,http://atomic.exist-db.org/articles/wolfgangs_talk.pdf)。

    2010 年 6 月 22 日 上午 09:51

  26. Brett Zamir

    我不熟悉 XQuery 更新功能,所以我会坚持使用 XQuery,但这里有一个可能的 SELECT 语句等效项(代码更少,更具函数式友好性)

    var db = window.openDb("CandyDB", "My candy store database");
    db.readTransaction(function(tx) {
      // Enumerate all the rows.
      tx.executeXQueryForEach(
        'for $row in collection("kids")//tr'+
          'return {$row/td[@class="name"]/string()}',
        function (div) {
          document.getElementById("kidList").appendChild(div);
        }
      );
    });
    

    或者,如果我们修改像 jQuery 这样的库以接受 XPath(因为将 CSS 选择器转换为更强大的 XPath 是合理的)并处理 XQuery 中使用的 collection() 和 doc(),我们可以使用与上面相同的 API 简化为

    db.readTransaction(function(tx) {
      // Enumerate all the rows.
      $('collection("kids") tr'.each(function (row) {
        $('#kidList').append(''+$(this).find('td[class="name"]').text()+');
      });
    });

    或者甚至包装事务

    $('db("CandyDB", "My Candy Store Database") collection("kids") tr'.each(function (row) {
      $('#kidList').append(''+$(this).find('td[class="name"]').text()+');
    });

    如果出于某种原因,你更喜欢关系模型而不是像这样简单的东西,只需使用类似这样的东西:http://github.com/nkallen/jquery-database

    请注意,上面的示例甚至没有演示它如何以相同的灵活性处理分层结构,而关系模型则做不到这一点。

    $('db("Classics", "Classic Literature Database") '+
      'collection("ShakespeareWorks") .irony'.each(function (ironicPassage) {
      $('#TheBardOnIrony').append(ironicPassage);
    });
    2010 年 6 月 23 日 上午 03:30

  27. Brett Zamir

    (讽刺的是,我将这些段落附加为关于讽刺的,而这些类可能代表莎士比亚而不是仅仅是讽刺,但无论如何)

    我知道你可以包装其他类型,但我难道是唯一一个觉得能够以这种方式处理数据非常吸引人的人吗?

    2010 年 6 月 23 日 上午 03:41

  28. Evan Ireland

    我对 IndexedDB API 有两个评论。

    (1)看起来你每个表只能有一个(主键)索引。因此,在非简单应用程序中的许多操作将不得不进行表扫描,排序和分页将成为一个问题。例如(对于排序和分页),假设每个公司都有零个或多个员工。我想编写一个查询来显示员工(按姓氏排序,然后按名字排序),并为每个员工显示员工姓名和公司名称。事实上,我只想显示该排序结果的第 M 行到第 N 行(以进行分页)。现在,如果没有在员工的姓氏和名字上建立索引,似乎不可能以任何有效的方式表达这一点。

    (2)我真的认为我们需要一个同步数据库 API。我喜欢 Web SQL 数据库 API 中同时提供同步和异步 API 的方式。我对缺少同步 API 的担忧是,组合会变成一场噩梦。假设我有一个 Employee 类,我希望能够生成代码,以便用户可以编写

    var e = … // 从某个查询中获取 Employee
    e.setPhone(555 123-45567);
    e.update();
    … // 在更新后做一些事情

    如果生成的 Employee 类必须使用异步数据库 API,那么我们无法将数据库访问封装在同步更新方法中。现在,如果更新可能需要无限长的时间,或者对于可能需要很长时间执行的查询(尤其是在索引不足的情况下),我理解异步 API 可能有用。但对于具有适当索引的表格上的精心设计的查询/更新,以及将数据库 API 封装在生成的类中,异步 API 简直是行不通的。

    我这里的想法集中在为移动设备(例如智能手机)构建商业应用程序。

    2010 年 6 月 27 日 下午 2:24

    1. Evan Ireland

      看看我自己的帖子,以及在查看规范 (http://www.w3.org/TR/IndexedDB) 后,我看到

      规范确实允许同步 API,但似乎不允许 UI 线程使用。

      规范确实允许使用替代索引,但尚不清楚它们是否可以是复合索引。

      因此,我需要深入研究一下,看看我们是否可以期望一个可供 UI 线程使用的同步 API 以及复合索引。

      2010 年 6 月 27 日 下午 2:50

      1. Shawn Wilsher

        我认为任何浏览器供应商都不愿意在 UI 线程上实现同步 API。这就是工作线程存在的意义。

        复合索引仍然是工作组正在讨论的内容。

        2010 年 6 月 30 日 上午 9:21

    2. Shawn Wilsher

      我认为您直接将表格的概念映射到此 API,这不是使用它的有效方法。

      2010 年 6 月 30 日 上午 9:22

  29. 巴西人乔

    我认为这太复杂了。在使用 JavaScript 时,我想将存储视为 JavaScript 对象,并放弃像表格这样的 SQL 概念。

    如果我必须对数据进行分区,我将简单地为所有对象添加一个“type”属性,并对其进行分类。

    如果您想阅读我的博客,我在博客上更详细地发布了我的想法。

    2010 年 7 月 5 日 下午 2:45

  30. Jeffry Engert

    添加数据的示例给出了一个对象是不可变错误的示例问题:objectStore(kids) 将以只读方式打开 objectStore……objectStore(kids,0) 将以读写方式打开它。

    2010 年 7 月 9 日 下午 11:16

    1. Shawn Wilsher

      是的,我们在构建工作之前就写了这段代码,这意味着它从未经过测试(并且可能存在像您发现的这样的错误)。我正在制作一个新的演示,该演示实际上在构建中运行(并且可以交互使用)。

      2010 年 7 月 10 日 下午 11:29

  31. Michal Gielda

    嗨,各位,

    我很高兴地发现 IndexedDB 已经加入了第一个测试版,并决定准备一个简单的演示/简单的高级 API,它具有有限的功能,这样您就可以直接获取它并自己测试 IndexedDB。我在我们公司的博客上发布了它:http://antmicro.com/blog/2010/07/async-indexeddb-js-api-test/

    如果您使用它,请告诉我它是否有效:) 当然,它远未完善,而且我不是真正的 js 编码员(我们主要做嵌入式系统),所以如果您认为可以改进,请随时告诉我。

    我会尝试在后续更新中添加更多功能。

    干杯,
    迈克尔

    2010 年 7 月 14 日 上午 4:25

    1. Michal Gielda

      或者您也可以使用 antmicro.com/blog.html :)

      2010 年 7 月 14 日 上午 4:27

    2. Shawn Wilsher

      不错!感谢您的付出!

      2010 年 7 月 19 日 中午 12:05

  32. Anentropic

    根据我对草案规范的阅读,可以

    1. 使用 Object 或 Array 实例作为值,例如
    var abraham = {id: 1, name: 'Abraham', number: '2107'};
    store.put(abraham);
    实际上,这是一种具有三个“字段”的“行”(“id”是自动生成的索引)
    2. 在存储的 Objects 的“name”字段上定义一个附加索引
    3. 从值范围返回记录,按“name”上的索引排序,例如
    var range = new KeyRange.bound('L', 'M');
    var cursor = index.openCursor(range);

    到目前为止一切顺利。在关于“键”的部分中,规范指出
    “只有具有自然排序的数据类型才能用作键。”

    但是,如果我们有这样的数据会怎样
    var abraham = {id: 1, name: 'Abraham', number: '2107', address: {postcode: 'NW1 1AA', city: 'London'}};

    我认为允许将它存储为值,但是,如果您在“address”字段上创建索引会怎样?这允许吗?看起来它将需要表现得像一个键,具有对具有“自然顺序”的类型的限制。

    理想情况下,我希望能够在复杂类型上创建索引,并为引擎在对索引进行排序时使用提供比较函数。(或者使用某种路径语法,例如在“address.postcode”上创建索引)

    具有复合键的索引也很有用。

    2010 年 7 月 17 日 上午 5:45

    1. Shawn Wilsher

      虽然您可以将 Array 存储为值,但不能将其用作键。

      在工作组中,我们正在讨论复合键的可能性,但它们可能不会出现在第一个版本中(这样我们就可以让一些稳定的产品发布,然后开始添加功能)。

      2010 年 7 月 19 日 中午 12:10

  33. 丹尼尔

    我不喜欢 IndexedDB 的方法,如果所有主要浏览器都实现相同的 API,我将不胜感激。
    由于 Webkit 和 Opera 已经支持 Web SQL(SQLLite),我认为仅出于一些学术原因而走另一条路是一个非常糟糕的决定。
    我正在使用 GWT 来实现我的 JavaScript 应用程序,因此,如果无法摆脱它,可以在 Web SQL 之上添加一个 GWT 布局以提供更简洁的 API。
    但如果选择另一种方法,它至少应该支持 SQLLite 的所有功能,否则它毫无价值。
    所以请:添加对 SQLLite 的支持,以便 Web 开发人员不必被迫使用 Google Gears 才能实现能够在所有主要浏览器上运行的离线功能丰富的 Web 应用程序!

    2010 年 7 月 20 日 上午 7:30

  34. Anentropic

    我得到

    错误:未捕获异常:[Exception… “组件返回故障代码:0x80460002 (NS_ERROR_OBJECT_IS_IMMUTABLE) [nsIIDBObjectStore.add]” nsresult: “0x80460002 (NS_ERROR_OBJECT_IS_IMMUTABLE)” location: “JS frame :: http://test/load.html :: anonymous :: line 74″ data: no]

    …当我尝试向我的新 objectStore 添加条目时。没有触发 onerror 事件,但我在 HUD 中看到了它,并且我的循环执行在此处停止,这是第一次迭代。

    有任何想法吗?

    到目前为止,其他所有内容都已正常工作,即根据上述示例创建/打开数据库。

    2010 年 7 月 21 日 下午 4:24

    1. Shawn Wilsher

      您处于该 objectStore 的 READ_ONLY 事务中。确保将其以 READ_WRITE 方式打开。我们需要改进错误消息(我遇到了它,并花了一个小时试图找出问题所在)。

      2010 年 7 月 21 日 下午 4:43

      1. Anentropic

        嗨,肖恩,

        感谢您的信息。我可能可以从那里追踪到它。我假设您上面的“添加孩子”代码示例也存在相同问题,因为我们都没有明确执行任何事务操作?(默认情况下为 READ_ONLY 吗?)

        很高兴看到更多关于事务的解释。例如,我不太清楚您为什么要在 JOIN 示例中使用事务,因为您只读取,而不写入。

        我已经弄清楚您必须在 indexedDB 上使用 moz_ 前缀,这要归功于上面的 Antmicro 团队…

        2010 年 7 月 22 日 上午 2:15

        1. Anentropic

          附注
          不仅仅是改进错误消息…也许应该调用实际的 onerror 处理程序?

          规范中写道
          “任意数量的读取器可以同时访问所有 objectStore。如果有任何读取器正在同时访问 objectStore,则不允许写入器。”

          因此,听起来每次执行写入操作时,都有可能由于事务锁定而出现故障,这甚至可能是在另一个选项卡中的进程,超出我们的控制,对吧?

          或者,正确的过程是在写入之前尝试获取 READ_WRITE 事务,并且该尝试将以 raw add() 无法实现的方式优雅地失败?我猜我必须试试!

          谢谢

          2010 年 7 月 22 日 上午 2:23

          1. Shawn Wilsher

            工作组当前的想法是,当我们知道某些事情会立即失败时,在调用点抛出异常比使用事件异步地进行更有用。这更容易调试,开发人员可以立即获得反馈。

            如果您有写入事务,它永远不会出现故障,因为您已经拥有访问该 objectStore 所需的锁。锁也不会自动提升,因此,如果您以 READ_ONLY 方式打开,它将始终为 READ_ONLY。

            希望这能更清楚地解释。

            2010 年 7 月 22 日 上午 11:01

        2. Shawn Wilsher

          有点。规范已经更改了很多,因此此代码不再完全准确。但是的,该代码存在相同问题。

          请注意,必须在事务中执行每个数据库操作。

          2010 年 7 月 22 日 上午 11:05

          1. Anentropic

            啊!我终于意识到,您可以从事务对象中获取 objectStore 并立即开始使用它…您不必等待 transaction.oncomplete 事件(该事件在您将对象添加到存储或执行其他操作后触发)。

            似乎缺少的一件事是删除数据库的能力?您可以删除 objectStore,但我没有看到数据库的等效操作。

            2010 年 7 月 26 日 上午 10:54

  35. TK

    我正在测试 IndexedDB。我可以在 objectStore 中插入数据。但是,我无法更新存储在 objectStore 中的数据。我尝试使用“add”方法,该方法带有两个参数,如下代码所示。
    ————————-
    transaction.objectStore(“my_object_store”).add(new_object, id).onsuccess = function(event) {
    //一些代码
    }
    ————————-
    第一个参数是“object”,第二个参数是应该更新的“id”。它失败了。如果您知道,请告诉我如何更新它。

    我期待 Firefox 4 的完成。

    2010 年 7 月 21 日 下午 11:48

    1. Shawn Wilsher

      我怀疑您遇到了上面 Anentropic 提到的问题。您需要以 READ_WRITE 方式打开事务才能写入 objectStore。如果您没有指定,默认情况下将以 READ_ONLY 方式打开它。

      2010 年 7 月 22 日 上午 10:58

  36. TK

    感谢您的回复。但是,我无法通过您的回复解决这个问题。因为我不是英语母语人士,我可能无法很好地向您解释这个问题。我知道我必须以 READ_WRITE 模式打开事务才能像您说的那样写入对象存储。因此,我可以将数据“插入”到对象存储中。但我无法一次性“更新”我插入对象存储中的数据。我想知道如何“更新”数据。虽然我执行了上面提到的代码来“更新”我之前插入对象存储中的数据,但我没有成功。如果您能理解这个解释,我将不胜感激。

    2010 年 7 月 22 日 下午 12:15

    1. Shawn Wilsher

      此测试代码向您展示了如何修改对象存储中现有条目。
      http://mxr.mozilla.org/mozilla-central/source/dom/indexedDB/test/test_key_requirements.html?force=1#33

      2010 年 7 月 22 日 下午 12:34

      1. TK

        感谢您的帮助!!!通过阅读您展示给我的测试代码,我能够理解如何更新插入对象存储中的数据。通过您的帮助,我开始可以使用“modify”方法和“addOrModify”方法。我理解如何使用它们与如何创建对象存储有关。并且,我将努力使用 IndexedDB 开发我的 Web 应用程序。我期待着 Firefox 4 的完成。非常感谢您这次的帮助。

        2010 年 7 月 22 日 下午 23:50

      2. TK

        我将 Firefox 4 从 beta 4 更新到 beta 5。我注意到 ObjectStore 对象在 beta 5 上没有 IndexedDB 的“modify”方法和“addOrModify”方法。但是 ObjectStore 对象似乎在 beta 5 上具有“put”方法和“clear”方法。要更新现有记录,我们似乎需要先“clear”现有记录,然后“put”新记录。

        2010 年 9 月 9 日 上午 06:39

        1. Shawn Wilsher

          是的,我们一直在密切关注规范的更改。请参阅 http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#object-store 了解预期情况。

          2010 年 9 月 9 日 上午 10:50

        2. TK

          我写了“要更新现有记录,我们似乎需要先“clear”现有记录,然后“put”新记录。”。但是,在那之后,我注意到当执行“clear”方法并指定现有记录的标识号(如下面的代码所示)时,对象存储中的所有记录都被清除。
          ————————————————–
          var request = my_object_store.clear(id);
          ————————————————–
          我的使用方式错误还是这是一个错误?

          2010 年 9 月 16 日 上午 01:12

          1. TK

            我注意到我们应该使用“remove”方法来删除现有记录,如下面的代码所示。
            ———-
            ver request = my_object_store.remove(id);
            ———-
            对于我提供的错误信息,我深表歉意。因此,要在 Firefox 4 Beta 6 上更新现有记录,我们似乎需要先“remove”现有记录,然后“put”新记录。但我希望我们能够使用“put”方法而无需使用“remove”方法来更新现有记录。

            2010 年 9 月 19 日 下午 19:53

  37. TK

    我一直致力于使用 IndexedDB 开发 Web 应用程序。当我为一个对象存储创建两个索引时,程序无法按预期运行。我们不能为一个对象存储使用两个索引吗?我认为我们可能希望通过两个或更多个索引检索对象存储。

    2010 年 7 月 28 日 下午 12:32

    1. Shawn Wilsher

      您的帖子缺少任何有用的细节,无法让我们真正帮助您。

      2010 年 7 月 28 日 下午 13:05

  38. Guido Tapia

    “continue”不是保留关键字吗?这意味着任何 IndexedDB 代码都会在非 indexeddb 浏览器中破坏 JavaScript(即使禁用 indexed db)?

    2010 年 7 月 29 日 下午 16:58

  39. TK

    为了解释我遇到的情况,我编写了示例代码,并将其发布在昨天。但是,该帖子今天没有显示。因为帖子太长,可能没有被此评论系统接受。我现在有了该帖子。我想展示它,但我不知道如何向您展示它。

    2010 年 7 月 30 日 上午 03:31

  40. Frank

    IndexedDB 是否可以在不同的操作系统之间移植?我正在为电子书开发应用程序,这些应用程序将把书籍内容保存在数据库中。如果数据库可以在任何操作系统之间移植,对用户来说将是一件好事。

    2010 年 7 月 30 日 上午 08:42

  41. TK

    因为我无法发布,所以我创建了临时网页。
    http://sites.google.com/site/usingindexeddb/

    如果您能理解这个解释,我将不胜感激。

    2010 年 7 月 30 日 下午 12:01

    1. TK

      上述程序的执行结果似乎表明,为一个对象存储拥有两个索引是不可能的。这是 IndexedDB 的规范还是我的实现错误?我想知道。

      2010 年 8 月 12 日 上午 05:41

      1. Shawn Wilsher

        规范或实现中没有任何内容会限制您可以在对象存储中拥有的索引数量(除了对象上的属性数量之外)。

        2010 年 8 月 12 日 上午 10:23

        1. TK

          我明白了。这太棒了。那么,为什么当我为一个对象存储创建两个索引时,上述程序会发生错误?

          2010 年 8 月 12 日 上午 11:24

          1. Shawn Wilsher

            可能有很多原因。如果您认为它有误,您应该提交一个关于它的错误报告。

            2010 年 8 月 12 日 上午 11:40

        2. TK

          这似乎是一个错误。它也存在于 Firefox 4 beta 3 中。

          2010 年 8 月 13 日 上午 10:08

        3. TK

          我使用的是 Mac OS 10.6.4 上的 Firefox 4 beta 3,尽管它忘记说了。

          2010 年 8 月 13 日 上午 10:13

          1. TK

            遗憾的是,这个错误仍然存在于 Firefox 4 beta 4 中。

            2010 年 8 月 24 日 下午 17:54

  42. Sri

    您可以在 http://tinyurl.com/ff-idxdb 找到一个 IndexedDB 游乐场。它包含 API 的示例。我写了它,因为我无法在其他地方找到文档。希望对您有所帮助。

    2010 年 8 月 4 日 上午 00:57

    1. Michal Gielda

      太棒了!您那里有一个非常清晰且有用的工具,谢谢您!

      2010 年 8 月 4 日 上午 01:43

  43. Dwight Vietzke

    我必须赞成 WebKit SQLite 的客户端数据库方面。SQL 适用于许多其他编程实现,那么为什么不在 JavaScript 中使用它呢?关键是,Mozilla(恕我直言)应该像 WebKit SQL 那样做,或者无论你叫它什么,只是为了创建一个近乎事实上的标准。使用相同客户端数据库语法和风格的浏览器越多越好。这是一个错失的机会,因为程序员更喜欢领导而不是追随。

    这并不是说 IndexedDB 不好或更好,只是让所有未来的浏览器使用通用的数据库策略会很棒(一个人可以梦想)。然后,IndexedDB 可以在下一代中成为领导者,为 JavaScript 提供额外的数据库实现。似乎 IndexedDB 已经找到了自己的位置(文档中心或基于 JSON),但我们现在需要的是一个更通用(敢说标准)的 JavaScript 接口。

    2010 年 8 月 8 日 下午 20:53

    1. Shawn Wilsher

      微软非常反对实现 WebDatabase,因此,即使 Mozilla 可以忽略它对规范的问题,您仍然不会在所有浏览器中都拥有它。将其与 Mozilla、WebKit(通过 chromium 团队)和 Mozilla 都致力于 IndexedDB 规范并为其努力相比。

      2010 年 8 月 10 日 上午 07:09

      1. greg

        那么,如果微软反对用 SQLite 数据库开发 IE,肖恩?这难道不是一个巨大的惊喜,因为他们销售关系型数据库,而且本来就不可能加入进来。对“规范”的质疑似乎是一个非常薄弱的借口,无法实现正在成为流行的后端持久层的东西。Mozilla 还有人真正负责吗?

        2010 年 9 月 2 日 下午 13:41

        1. Christopher Blizzard

          Greg,你的夸张根本没有帮助你传递信息。

          我们已经非常清楚地表达了我们对当前数据库规范的看法。那里存在真正的问题,其中一些是根本性的。

          至少有三个主要的浏览器供应商有兴趣实现 IndexedDB。这似乎是值得投资的东西。

          2010 年 9 月 9 日 上午 10:09

  44. Morn Jaon

    我是一个 IndexedDB 的新手,我想向您问一个愚蠢的问题:IndexedDB 使用什么样的数据库文件?.db?还是 .XML?

    2010 年 8 月 11 日 下午 18:00

    1. Shawn Wilsher

      API 没有指定它,所以它并不重要。

      2010 年 8 月 12 日 上午 10:21

      1. Morn Jaon

        所以,当我们创建 IndexedDB 并使用它时,不需要知道是什么类型的数据库,也不知道它在哪里?
        我不擅长 IndexedDB 的 API。大多数对我来说仍然很奇怪。我还不是一名熟练的 Web 编码人员。

        2010 年 8 月 12 日 下午 22:13

        1. Shawn Wilsher

          不,它只是一个 DOM API。

          2010 年 8 月 13 日 下午 14:13

          1. Morn Jaon

            你能展示一些学习教程或参考资料吗?我真的需要一些东西来更深入地了解它。

            2010 年 8 月 15 日 上午 05:35

  45. TK

    我们应该如何看待 IndexedDB 的安全性?我正在使用 IndexedDB 开发小型 Web 应用程序,然后我正在采取类似于服务器应用程序的措施来防止我的应用程序发生跨站请求伪造。也就是说,我将用户请求发送到服务器一次,然后进行验证,最后将写入用户浏览器 IndexedDB 的指令发送到服务器。但是,由于 JavaScript 具有“同源策略”,我认为我可能没有必要将请求发送到服务器并进行验证。您对此想法有什么看法?

    2010 年 8 月 13 日 下午 13:24

    1. Shawn Wilsher

      我认为这是您应该向 工作组 提出的问题。

      2010 年 8 月 13 日 下午 14:14

  46. Pete

    对于所有喜欢 WebDatabase 方法的人来说,有一个扩展可以将 WebDatase API 公开给内容。它被称为 ZoooS Widget Runner
    https://addons.mozilla.org/en-US/addon/70769/

    2010 年 8 月 24 日 上午 09:17

  47. Meni

    我刚读完这篇文章,还没有看评论,所以请原谅我贸然评论,如果我表现得愚蠢,那只是因为我对这种情况有强烈的感受。这难道不是 SVG 和 VML 的翻版吗?据我所知,当时是自尊心和骄傲在作祟,最终我们所有人都因此而失败。如果当时我们能达成一个向量标准协议,现在的网络会更好。

    我主张把来自谷歌、苹果、微软、Mozilla 和 Opera 的人召集到一起,直到达成一致意见才能离开房间。让网络快速发展。在他们被困期间,请合理分配披萨:-)

    天哪,如果 JavaScript 是由你们这些人创造的,我们今天还在等待它呢 ;-) 如果说有什么教训要吸取,那就是:选一个吧,谁在乎它是否完美,没有人会因为这个把你关进监狱。

    祝好(顺便说一下,感谢 FF,没有它我活不下去)

    2010 年 9 月 19 日 00:53

    1. Greg Quinn

      > 天哪,如果 JavaScript 是由你们这些人创造的,
      > 我们今天还在等待它呢 ;-)

      嗯,我认为 JavaScript *确实* 是由这些人发明的……

      2010 年 9 月 19 日 19:58

      1. Emmanuel

        Javascript 最初是由一个人/公司(Brendan Eich/Netscape)发明的。如果它需要从一开始就由来自多个竞争公司的委员会发明和达成一致,我不会感到惊讶,因为他们可能要等 5 年才能就应该包含哪些功能达成一致,再等 5 年才能将其批准并推荐使用,最后再等 5 年才能让我们所有人在不同浏览器上使用基本一致的功能。

        可悲的是,历史反复证明(VHS/BetaMax、HD/BluRay),我们都会被迫选择学习其中一种,或者在最终在市场上胜出之前花额外的时间学习两种。

        客户只关心最终的结果是否按时完成,我只想要能用的东西,如果我已经知道,那就更好了。如果我必须学习新东西,我会的。我只是不想为了在所有浏览器上做同样的事情而学习两种东西。这和跨浏览器兼容性的问题一样糟糕。

        2010 年 9 月 20 日 14:01

  48. JoshuaBln

    Internet Explorer 9 beta 版现在是否支持 IndexedDB?我无法在 IE9 上测试我的代码,但在 Firefox 4.0 beta 6 上运行良好。

    2010 年 9 月 23 日 01:37

  49. Matt

    我认为将 B 树数据库作为基础是有意义的。我同意直接使用它看起来过于复杂,但我们实际上只需要一个 jQuery 插件就能实现优雅。你实际上可以在这基础之上构建性能良好的关系型、层次型或面向文档的数据库。

    希望主要的浏览器能很快采用它。

    2010 年 11 月 1 日 20:01

  50. Joe Shawfield

    我感谢那些站在这些决定和讨论最前沿的人的努力。把你的技术考量和信念摆在所有人面前,并喋喋不休地谈论它们,需要很大的勇气。这极大地有利于我们所有人!

    我个人想要两者兼得。我喜欢将关系型结构数据存储在 SQL 侧的语法,但也喜欢 JavaScript 方法和编程模型。

    我确实看到了各种情况,特别是在 Web 上,我想要/需要存储对象。我希望将它们持久化,以便在以后的客户端应用程序中使用。

    所以我想同时使用这两种存储方式。

    最后我意识到,如果我使用 SQL 选项,并且需要使用它或将其发回,我需要进行更多封送处理才能在客户端使用它或通过 HTTP 模型获取/发送它。我必须在一端打包,并在另一端解包。

    感谢大家

    2010 年 11 月 4 日 03:13

  51. Morn

    我不知道为什么 firefox 4.0b7 更改了 indexedDB API,我之前做了一个演示,它在 beta 2 中运行得很好,但现在在 beta 7 中完全无法运行。你知道关于 indexedDB.open() 方法的任何信息吗?

    2010 年 12 月 6 日 01:48

  52. Chad

    有人知道 Firefox 4 B7 的 vacuum sql 清理程序的替代方案吗?

    2010 年 12 月 11 日 17:04

  53. Jesse Morgan

    大家好,这里有一些有趣的讨论。

    我认为 Mozilla 的方向是正确的。如果我们现在不做这件事,在网络应用程序开始取代客户端应用程序之前,我们只会陷入一个混乱的局面,而这个局面将难以修复。

    看看一个短视的产品设计如何通过不考虑长远的影响而损害互联网的技术发展。我说的是 Internet Explorer。

    虽然前面几篇文章中那个英语不太好的家伙不太好理解,但我同意,将数据以表格和列的形式进行考虑的既定模型对于 Web 来说是一种过于限制性和特定于案例的强制性最低公分母。定义更宽松的对象存储在这里更有意义,正如已经提到的,如果需要,可以在这之上实现更严格的表格式语义。

    我认为我们确实需要一种清晰简洁的语法来查询这些对象存储。同样,正如已经提到的,这对于更高级别的实现来说是有意义的……

    就一种简单、灵活、但结构化且有限定义的查询方法而言,我不禁想到微软的 LINQ——或者更具体地说,整个 IEnumerable 接口和随附的 LINQ 方法。

    为了清楚起见,对于那些熟悉 LINQ 的人来说,支持 LINQ 查询所需的对象方法与其类似 SQL 的查询语法是不同的,后者只是编译成返回对象上的方法。你仍然可以在不编写基于字符串的查询的情况下使用 LINQ。

    快速搜索一下,发现了一些这个的 JavaScript 实现!这让我有点兴奋,即使只是为了玩玩。

    http://linqjs.codeplex.com/
    http://jsinq.codeplex.com/

    示例
    var result =
    customers.groupBy(function(customer) {
    return customer.lastname;
    }).
    select(function(g) {
    return {lastname: g.key, count: g.count()};
    }).
    orderByDescending(function(r) {
    return r.count;
    });

    var query = new jsinq.Query(‘
    from customer in $0
    group customer by customer.lastname into g
    select {lastname: g.key, count: g.count()}
    into r
    orderby r.count descending
    select r
    ‘);

    query.setValue(0, customers);
    var result = query.execute();

    另外,一个强制性的“JOIN”示例。
    from order in $2
    join product in $1 on order.product equals product.id
    select {customer: order.customer, price: product.price}
    into p
    group p by p.customer
    into g
    select {customer: g.getKey(), sum: g.sum(function(q) { return q.price; })}
    into c
    join customer in $0 on c.customer equals customer.id
    orderby c.sum descending
    select {name: customer.firstname + ‘ ‘ + customer.lastname, ‘sum of all purchases’: ‘$’ + c.sum}

    由于 JS 是一种基于原型的语言,因此在可枚举对象(只是数组吗?)上支持查询方法应该相当容易完成。从我发布的链接来看,情况似乎就是这样。

    真正的难点在于它与 DBIndex 之间更低级别的交互,以便可以惰性地进行数据迭代。但我相信这是可以做到的!

    2010 年 12 月 12 日 04:02

  54. Paul

    作为一名 Web 开发人员,从我的角度来看,解决方案很简单。在我的应用程序中放弃 Firefox 支持,就像以前浏览器大战中许多人所做的那样,并使用 Chrome Frame 处理 IE 用户。由于 Firefox 仍然是少数浏览器,所以这实际上非常简单。

    对 Mozilla 没有冒犯之意,但我真的没有打算为了别人的政治游戏而推迟使用有效的关键技术。

    对我来说,最好是声明支持 SQL92 或者起草一个新的类似 SQL 的规范。如果当前的实现不符合,那么就应该被认为是错误。

    2010 年 12 月 27 日 22:29

    1. Chris

      “由于 Firefox 仍然是少数浏览器,所以这实际上非常简单。”

      胡说。截至 2011 年 4 月,FF 的市场份额为 42.9%。下一个最大份额是 Chrome,为 26.5%。

      2011 年 6 月 2 日 14:52

      1. Chris

        Dude,
        不要使用 w3schools.com 来获取 Web 统计数据,尽管他们的网站上没有明确说明,但我确信这些统计数据来自他们网站的用户,因此他们的统计数据存在相当大的样本偏差——简单地说,Web 开发人员和有志于成为 Web 开发人员的人更有可能使用 FF 或 Chrome。
        如果你能找到一些更具代表性、更好的统计数据,你可能会发现 IE 仍然领先(它是 Windows 的默认选项,而且不会有太多人更改),其次是 FF,然后是 Chrome。Opera、Safari 和 Rockmelt 可能分别占 1% 或 2%。

        2011 年 8 月 29 日 02:28

  55. Clay Lenhart

    C# 从 LINQ 中获益匪浅,JavaScript 也没有任何理由不能享受这种好处。简而言之,答案是修改 JavaScript 语言以支持查询。

    看看这里的 Pig 脚本(http://www.readwriteweb.com/cloud/2011/01/how-twitter-uses-nosql.php)。Pig 脚本完全可以理解。你可以很容易地看到像 LINQ 嵌入在 C# 中一样,Pig 语言嵌入在 JavaScript 中。

    2011 年 1 月 4 日 15:32

  56. John

    @Paul,我不敢相信你自称是一名 Web 开发人员,却要放弃迄今为止发展最快、最受欢迎的 Web 浏览器之一。

    现在大多数移动用户都在使用 Webkit(iOS 和 Android),而 Firefox 几乎完全符合 Webkit。我发现最流行的浏览器(Chrome、Safari 和 Firefox)之间几乎没有不兼容的地方。

    Firefox 4 提供了一些令人惊叹的新技术,它将推动在线应用程序和游戏进入下一代。其他浏览器也会效仿,因此,如果你想继续担任 Web 开发人员,我强烈建议不要在你的应用程序中放弃对 Firefox 的支持。

    2011 年 1 月 14 日 08:20

    1. Paul

      需要明确的是,我并不是说完全放弃对 Firefox 的支持,而是指那些将使用离线存储的应用程序。

      我实在难以理解,把一整套新的查询语言塞进 JavaScript 会怎样才能不让人头疼,特别是考虑到这种情况会让我们回到遍历 B 树的时代。

      WebDB 是一个现有的标准,在生产级浏览器中已投入使用。可以针对它开发离线应用程序,而无需支持/维护仅在浏览器实验版本中使用的实验性标准。

      如果我不得不尝试为开发任何东西而辩护,那我肯定保不住 Web 开发人员的工作。

      2011 年 1 月 15 日 09:32

      1. Shawn Wilsher

        WebDB 的问题在于它从未达到 CR 状态,实际上现在被认为是一个已弃用的标准。

        2011 年 1 月 18 日 15:10

    2. satish

      你能解释一下 Visual Studio Professional 中的数据库连接吗?

      2013 年 1 月 29 日 07:06

  57. codeguru413

    我个人并不是 IndexedDB 的粉丝…… 至少现在还不是。一方面,我对表格和数据库术语很熟悉。然而,这不是说我们应该使用这种存储访问和开发方式的充分理由。使用“对象”的概念是有意义的,因为这是我们在日常物理生活中所接触到的,因此在计算和存储方面是一个很好的类比。从上面的例子中我没有看到的是更复杂的关联逻辑……这对将对象相互关联至关重要。现在,也许上面的例子过于简单,只是为了展示 IndexedDB 并将其与提议的 WebDatabase 提案进行对比(该提案不可否认地存在严重缺陷,因为截至目前,它主要处理 SQLite)。

    但是,在我们跳上 Indexed DB 的 bandwagon 之前,让我们考虑一种可以使 WebDatabase 工作(或者,即使在使用对象关系模型而不是表格关系模型方面增强 IndexedDB——如果你仔细想想,当你考虑到它的核心是关系代数时,它们并没有那么不同)的替代方案。无论如何,主要的问题是数据库(例如 MS SQL Server(或 CompactSQL)、SQLLite 等)都使用不同的 SQL “方言”——轻描淡写地说。由于大多数这些“紧凑”和精简的数据库都是免费提供的,因此它们之间没有理由需要使用不同的 SQL 方言。也许应该有一个单独的 Web 专用 SQL 标准,所有这些不同的紧凑型数据库都将使用(或者专门为 WebDatabase 或 IndexedDB 创建的数据库引擎),以便促进跨浏览器、跨数据库的支持?我知道,这似乎很新颖……我不明白为什么我们不能都克服自己,让它实现。

    无论如何,只是我的一点想法……你不必对我生气。如果你不喜欢我说的话,那就继续读别的东西,或者继续做你现在做的事情。

    最重要的是,我只是鼓励所有努力使它成为现实的人尽可能简化查询界面。数据为王,许多没有正规数据库技术知识的人需要查询和分析这些数据——甚至在运行时创建“查询”。

    2011 年 2 月 1 日 上午 10:06

  58. Rafal

    你可以在 Firefox 4 beta 10 或 11 中运行这篇文章中的示例代码吗?
    我的问题是,在调用 mozIndexedDB.open() 后触发的成功事件没有 result 属性,我无法获取到数据库实例?这是 Firefox 的错误还是我做错了什么?

    2011 年 2 月 14 日 上午 00:57

  59. Rafal

    好吧,我自己找到了答案。在 Firefox 中,你必须从请求对象而不是事件对象中读取结果。我不明白为什么这样做,因为 Indexed DB 草案中说的是另外一回事。

    2011 年 2 月 14 日 下午 14:18

  60. Ben Dilts

    这些代码示例读起来就像 Web SQL 的广告。在每种情况下,我都会付钱来使用 Web SQL 代码而不是 Indexed DB 代码。

    我尝试在 Firefox 4 中使用 IndexedDB 实现了一个简单的单表、单索引设置,代码写起来非常痛苦,性能也非常糟糕(简单地循环遍历大约 1KB 的 200 个对象需要 4 秒),我准备支持任何东西,除了这个。

    2011 年 3 月 2 日 上午 00:09

  61. ray

    我相信代码示例说明了一切。除了“存储儿童……”以外,每个示例都比 IndexDB 更长。这有什么帮助呢?

    2011 年 3 月 7 日 下午 21:46

    1. Paul

      关于循环遍历儿童关系的对象,究竟是什么被索引了呢?

      2011 年 3 月 7 日 下午 22:46

  62. Mike Wilson

    只是我个人的看法,但为什么 Mozilla 没有简单地支持 WC3 最初指定的 WebDB 呢?说真的?你必须自己编写连接策略吗?现在是 2011 年了,但 Mozilla 却实施了一种存储策略,基本上抛弃了大约 40 年的扎实的关联理论(Codd 等人)?即使你不喜欢 SQLite 的专有(ish)性质,他们难道不能想出至少具有 SQL 连接语法的方案吗?

    Grrrr。我目前正在为我正在编写的产品进行 HTML5 功能审计,由于这个原因,我正在认真考虑排除 Firefox 作为支持的浏览器。谷歌浏览器万岁!

    2011 年 3 月 21 日 下午 21:56

    1. Christopher Blizzard

      Chrome 也可能会支持 IndexedDB。

      2011 年 3 月 22 日 上午 09:58

      1. Greg

        希望 Mozilla 会效仿 Chrome,支持两种存储技术 :)

        2011 年 3 月 22 日 上午 10:13

        1. Shawn Wilsher

          为什么 Mozilla 要实施一个已经被标记为已弃用的规范?

          2011 年 3 月 22 日 上午 10:19

          1. Marcelo Cantos

            你们对这些标准有重大影响。抱怨它已经过时只是找借口。为什么不能直接在它所处的任何状态下拾取标准,并修复它存在的所有问题呢?你们抱怨标准引用了特定实现以及随之而来的独立定义语言的困难,但大部分工作已经完成。SQLite 支持大多数 SQL-92 语法。因此,作为起点,Web SQL Database 可以定义 SQL-92 的一个子集,它恰好也是 SQLite 语法的子集。

            现在,我并不完全天真。我知道这比这更复杂,但你们真的指望我们相信这比你们现在正在做的事情更费力吗?

            2011 年 3 月 23 日 上午 04:15

  63. John Smith

    是的,这个决定非常糟糕。
    是的,借口很可笑。
    好吧,让我们思考一下。
    请纠正我,如果我错了,但应该有一些理由。
    Mozilla 的人不是白痴和蠢货(如 Kevin Layman 所说)。
    那么,谁从阻碍通用浏览器 SQL DB 标准的接受度中获益最多?
    显然是拥有桌面电脑的公司。
    谁损失最大?
    显然是希望将所有应用程序迁移到网络的公司。
    Mozilla 站在前者的立场,而不是后者的立场,这是否不合常理?
    是的,是,但我们并不知道幕后的一切。
    是否有可能有一些钱易手,或者有人在 Microshaft 获得了高职位?
    谁知道呢?

    无论如何,后果是什么?
    企业是否应该开始将他们的 intranet 应用程序迁移到基于 webkit 的浏览器?
    Mozilla 的举措是否会像 Chrome Frame 一样被绕过?
    是否会有一些基于 WebDatabase 的杀手级应用程序出现,并抢夺 Mozilla 的市场份额?

    想法?

    2011 年 4 月 4 日 下午 22:03

    1. Dan

      “是的,是,但我们并不知道幕后的一切。
      是否有可能有一些钱易手,或者有人在 Microshaft 获得了高职位?”

      @John Smith - 你是在跟我开玩笑吗?Mozilla 是一个 501.3C 非营利组织,所以新 IndexedDB 标准是通过一些秘密数据库 hush-money 阴谋而产生的想法是可笑的。

      “8 号收银台的锡箔纸多少钱,这里有一位先生需要大量锡箔纸,他似乎是在做帽子。”

      2011 年 6 月 13 日 上午 08:16

  64. Jesse Morgan

    那些大声疾呼要求支持 SQL 的人——SQL 非常过时。现在是 2011 年了!我们可以做得更好,我们为什么要以牺牲进步为代价来支持旧的语法呢?

    我之前评论过 indexdb 的类似 LINQ 的语法——我认为这对于对象存储或 NoSQL 风格的存储来说会非常有效。

    微软研究院似乎同意我的观点(虽然我对 MS 研究没有信心——但这篇文章很可靠)
    https://queue.org.cn/detail.cfm?id=1961297

    2011 年 4 月 7 日 下午 17:41

    1. Paul

      只有引入了新的功能,它才算是一种进步。

      据我所知,LINQ 是 SQL 的抽象层(甚至有内置的实用程序可以查看由 LINQ 生成的 SQL 查询)。虽然 LINQ 的语法有所不同,但 SQL 中存在的很少有功能是在 LINQ 中找不到的。

      这显然不是 IndexedDB 的情况,它没有数据实体之间关系的概念,你必须自己维护。无论现在是哪一年,循环遍历对象列表以自行过滤它们不仅在语法上更多工作,而且在计算上也更多工作。

      任何在行业中工作了一两年以上的开发人员现在都应该知道,只要功能仍然存在,语法在很大程度上是无关紧要的。我并没有执着于 SQL 语言,我相信还有其他更易于阅读/维护的查询方法。但是,如果我们要对持久存储使用对象关系模型,那么必须保证关系完整性。IndexedDB 中没有这个,在它出现之前,它与 webDB 相比是一个劣质标准。

      因此,虽然它可能是一个良好的开端,但我很难证明在使用它时花费的时间和精力,因为我可以使用 Chrome 和 Chrome Frame,最终得到一个稳定、可维护的应用程序。

      2011 年 4 月 8 日 下午 17:31

      1. Jesse Morgan

        我不认为你对 LINQ 的理解是正确的。

        LINQ 基于 IEnumerable 接口。这个概念是,任何可以枚举的对象都符合一个单一的接口标准,可以使用统一的模型和语法对其进行操作、查询和关联——结果将生成为隐式运行时类型(js 通过成为原型来处理这一点)。
        没有预先存在的关系。LINQ 绝对不是 SQL 生成器。LINQ to SQL 是用于查询 SQL 的 LINQ 实现。同样,LINQ to Object 或 LINQ to XML 对其他数据存储类型执行相同的操作。

        .NET 实体框架确实存在,用于提供对象之间的预设关系,并且它确实与 LINQ 集成,但这不是必需的。我相信这就是你感到困惑的地方。

        2011 年 4 月 11 日 下午 18:36

      2. Jesse Morgan

        此外,迭代结果集并不一定在计算上更昂贵。我不确定是什么让你有了这种想法?

        无论你使用的 API 是为你执行迭代,还是你亲自执行,它总是在某个地方被执行。

        在 IndexedDB 的情况下,你可以获得更低级别的控制,可以自行执行此操作。正如已经表明的那样——另一个 API 可以利用 IndexedDB 以打包的方式提供这种关系“完整性”。

        这种开发方法对于像 jquery 这样的库来说非常有效

        2011 年 4 月 11 日 下午 18:42

        1. Paul

          这不是政府项目。

          关于 LINQ 的观点已经提出,我把它和 LINQ to SQL 混淆了。但我不得不说,如果 SQL 数据库循环遍历整个数据集,这被认为是“全表扫描”,这表明你至少需要定义一些索引。

          我认为你已经说出了为什么有那么多反对 IndexedDB 的原因。它是一个低级别的数据库存储解决方案,这意味着我们必须从头开始重新设计查询工具、报表工具、分析工具等。

          这不是政府项目。我认为认为可以同时进行努力并不算过分,事实上,web 由许多服务于相同目的但具有不同优点和缺点的标准组成,这使设计人员和架构师可以选择最适合每个应用程序的标准。

          软件行业已经见证了无数次这样的根本性变化,随着新技术的成熟,它们会取代旧技术,因为它们在实际应用中具有优势。除了更类似于 javascript 的语法之外,IndexedDB 在新功能方面没有任何优势。

          事实上,它的功能比 WebDB 少。这些示例表明,程序员在进行连接操作时需要自行处理,没有关于聚合或防止出现孤儿记录的示例。

          我个人对使用新技术没有任何问题,我发现在这个行业中,人们对新技术的抵触很奇怪。但我也无法理解这个行业中很多人对语法的执着。我使用过很多技术,坦率地说,我发现语法很少会产生影响。尤其是当像这样的示例表明新语法会导致更多工作量时,我更看不出新语法的吸引力。

          我相信 IndexedDB 最终会成熟到提供优势,或者会被替换成具有优势的技术。在此之前,我无法为移动应用程序提供对 Firefox 的支持,因为我在所有其他浏览器(包括通过 Chrome Frame 的 IE)中都内置了对 WebDB 的支持。

          2011 年 4 月 23 日 下午 09:09

          1. Jesse Morgan

            再次您好,
            感谢您的详细回复。

            我认为对象存储模型更适合现代环境,也更适合我希望 Web 技术能够实现的无处不在的时代。能够通过公共属性索引来引用类似对象的存储非常强大。

            它符合 JavaScript 的要求,因为它保留了原型的类型灵活性。

            我认为,如果您试图将对象存储用作 SQL 存储,那么您是对的;这是条漫长的路。

            它的强大之处在于您在存储中不受限于表格模式。您只需要确保在存储值上设置有意义的键或键属性;剩下的都是自由格式。

            例如,名为“Entity”的对象存储。
            现在,“Entity”存储了人和公司的记录。

            因此,当我们在该存储中存储对象时,我们确保为每个对象分配唯一的“EntityID”作为键,但其值除了具有名为“实体类型”的属性(该属性暗示了预期存在的其他相关属性)外,几乎没有相似之处。

            我们可以索引“实体类型”以加快查询速度,但本质上,您拥有一个根据需要拥有不同列的 SQL “表”。

            在这种情况下,“Person”记录可能包含姓名、姓氏、用户名、密码、历史记录[]、朋友[]。

            后两个属性是更多对象或 EntityID 的数组。

            我个人不是数据库级别关系管理的坚定支持者。这看起来像是对调用 SQL 查询的代码质量不佳的一种敷衍。

            别误会我的意思,这显然是一个笼统的概括,但我认为您是对的,数据库系统的主要功能是索引和及时访问信息。我认为关系管理是其次的,在这种情况下,我很乐意在更高的层面上进行管理。

            还有,SQL 本质上是一个美化过的文本存储。当然,我们也有数字数据类型,包括日期。您可以存储“blob”,但它们是哑的,数据库引擎无法理解它们。

            我还不完全清楚的是,IndexedDB 是否会将键值对中的“值”视为具有属性的标准 JavaScript 式对象,并允许对对象的属性进行查询。

            如果我必须使用 SQL 数据库,这将是一个巨大的优势,因为我节省了将数据序列化和反序列化为文本的时间。

            2011 年 4 月 23 日 下午 17:03

  65. Jesse Morgan

    也许我应该先等一下再发布,这样我就可以合并回复;

    我们现在处在一个技术的关键时期。最近有一篇文章指出,我们现在只有行业和对昂贵的液体火箭技术的依赖,这要归功于一系列特定事件,包括二战、希特勒对 V2 火箭的迷恋以及随后的冷战和洲际弹道导弹技术的飞速发展。

    最终结果是,行业和“标准化”技术都与液体火箭推进有关,这可能不是最好的解决方案,但由于“重新开始”的成本以及对该领域经验的投资和抗拒变化,我们被束缚住了。

    这种情况也同样如此。我们正在讨论未来的平台,因此有必要评估构成基础的技术。

    2011 年 4 月 11 日 下午 18:59

  66. Shiby

    IndexedDb 对我来说不起作用,代码很简单,但在尝试打开数据库时出现错误。错误:未捕获异常: [Exception… The operation failed for reasons unrelated to the database itself and not covered by any other error code. code: 1 nsresult: x80660001 (NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR) location: file:///D:/shiby/html5/IndexedDB/IndexedDbSampleFF.htm Line: 14]

    有人知道吗?

    2011 年 5 月 24 日 上午 02:08

    1. louisremi

      您使用的代码的更多详细信息将非常有帮助。
      Louis-Rémi

      2011 年 5 月 24 日 上午 05:45

      1. Shiby

        它与上面的代码类似。我仍然会在这里粘贴我的代码。

        var request = window.mozIndexedDB.open(“todos”);
        request.onsuccess = function(event) {
        var v = “1.0”;
        var db = request.result;
        };

        在调用 open 方法的那一行出现异常。

        2011 年 5 月 24 日 下午 22:30

  67. […] 如果你曾经做过 SQL 数据库编程,就会发现这些概念都十分雷同。二者主要区别在于,对象存储没有结构化查询语言的概念。你不需要类似”SELECT * from USERS where ACTIVE = ‘Y’”这种语句。你需要做的是使用对象存储机制提供的函数,在名为 USERS 的数据库上打开一个游标,遍历所有记录,过滤掉不活动的用户,使用访问函数读取剩下记录的所有字段。An early walk-through of IndexedDB 是一篇关于 IndexedDB 如何工作的不错的教程,给出了关于 IndexedDB 和 Web SQL Database 的对比。 […]

    2011 年 6 月 13 日 下午 22:05

  68. Bill Harten

    快 50 倍?“我从未说过 [表] 单元格中的数据必须是原子的”—— Ed Codd,关系数据库之父,1999 年旧金山超大型数据库大会。我去了大会,只是为了听他说这句话。

    他正在为自己的发明辩护,并解释为什么对象存储通常比类似的关系实现快 50 到 100 倍。他解释了为什么该行业在最初的关系数据库实现者的操控下走错了方向,他们只认识到表格单元格中比原子值(字符串、整数、浮点数、blob 等)更复杂的东西。

    Codd 的关系代数展示了如何将复杂现实世界信息结构规范化(分解)为一组二维表,并通过关系运算符(投影、选择和连接)重新构成。问题是,从许多较小的原子部分重新构成需要比将相同信息存储在更少的复合部分中花费更多工作。这就是为什么现代对象存储、XML 数据库、面向对象和旧的层次数据库(如 MUMPS 和 IMS,虽然古老,但它们做对了)能够比关系数据库快得多地处理复杂数据。关系数据库在过去 40 年中能够生存和繁荣的唯一原因是摩尔定律带来的硬件加速。

    真的吗?1984 年,我为 LDS 教会 FamilySearch 数据库(当时世界上最大的家谱数据库)创建了一个关系数据库和一个基于 XML 的(GEDCOM)对象数据库。(我知道,当时还没有 XML)。两者都被实现并部署在生产环境中,以满足相同的需求。由于组内不确定,我们同时进行了这两个项目。关系版本被仔细地索引和半规范化,以优化性能。尽管如此,基于 XML/GEDCOM 的系统速度快了 50 倍以上,不是 50%,而是 50 倍!一个完整的家庭、其成员和详细信息都存储在一个压缩的物理块中。部署在一台普通的 1984 年 PC 上,它比我们价值数百万美元的大型机上的关系系统运行速度快得多。这是由于数据的现实世界复杂性和将数据分解与保持数据在一起的效果。大型机最终负责准备数据以部署在 CD 上。

    教训?IndexedDB 存储复杂对象的能力,如果得到充分利用,可能会带来更高的性能。连接和遍历语义的缺乏、笨重的语法和其他问题在其他设置中已经解决过;我们只需要集中精力、发挥最佳想法和数据。

    2011 年 6 月 27 日 下午 13:15

  69. Paul

    在我看来,这似乎是一个很大的倒退。

    SQL 不仅仅有一个“SELECT * FROM mytable”命令是有原因的(据我所知,这本质上就是 IndexedDB 所拥有的)。

    在 IndexedDB 中可以实现的任何操作,都可以在 SQL 中以类似的难度实现,但那些在 SQL 中很容易实现的操作,在 IndexedDB 中看起来非常复杂和/或效率低下。也许在 IndexedDB 中有一些更容易的操作,但从这些示例中看不出来。

    例如,说磁盘 I/O 相比 JavaScript 读取和过滤数据速度慢,这是非常不诚实的。这忽略了缓存的事实。考虑对一个 50 MB 的数据库进行顺序扫描。如果数据库必须从磁盘读取,那么磁盘速度将使 JS 和编译语言之间的差异对整体时间的影响非常小。但是,如果数据库已加载到内存中(无论是在数据库引擎中还是在操作系统缓存中),那么 JS 和编译语言之间的差异将更加显着。

    2011 年 6 月 30 日 上午 04:09

    1. Bill Harten

      您的评论忽略了性能,并暗示代码简洁是重中之重。当您有数千个并发事务和数 TB 的复杂相互关联数据时,性能往往决定着可能性。

      我并没有说提速是因为编译代码,而是因为关系实现中必须访问的离散物理块的数量,而层次实现中的块数量要少得多。我报告的提速不是理论上的,而是实际的。它是在真实优化数据库、真实优化硬件和真实用户负载下测量的。提速为 50 到 100 倍(不是 50%,而是 50 到 100 倍)。在大型系统中,数量级的性能提升非常重要,您不觉得吗?

      我上面提到的测量包括缓存,并不虚假。这些数字是实际的性能比较,而不是预测的。它们是在具有巨大缓存的大型内存超级计算机上测量的。但是,缓存能够解决的问题也有限。性能主要取决于为满足查询必须从磁盘检索的物理块数量,而大型数据库默认情况下不适合缓存。关系实现将您需要的数据分散在许多块中,而层次实现可以将复杂的数据包在一个物理读取操作中交付,这取决于它的组织方式以及需要如何遍历它。

      这就是为什么 IndexedDB 在处理复杂的关联数据时,能够以树状结构进行分组并根据遍历需求进行组织,从而比传统的关联实现方式快得多。这也是为什么 IndexedDB 是一个朝着正确方向迈出的大步。如果你不喜欢这种语言语法,可以建议其他替代方案,但不要将语法与硬件在底层执行的实际工作量混淆。

      2011 年 9 月 8 日 08:31

      1. Robert Brown

        嗨,Bill,

        你的示例速度会快 50 到 100 倍,因为你存储的数据高度层次化,因此我猜测它只有一个定义的关系:父节点拥有子节点,它遍历整棵树。如果你的系统中存在更多关系,例如父节点拥有子节点并且为雇主工作,那么你会看到完全不同的结果,除非你在 XML 数据库中多次存储数据,这似乎是在自找完整性问题或循环引用问题。

        如何在你的 XML 中解决循环引用?我很好奇,因为你说整个家庭被存储为单个数据块。也就是说,如果发生不可预见的情况(不幸的是,这种情况确实会发生),并且某人与他们的后代生育了一个孩子,那么当你遇到那个后代时,如何存储整个家庭,因为他们上面的整棵树不能无限地重复,对吧?

        专用数据可以通过专用存储机制进行加速,我们谈论的是(通过 Web 标准)一种通用的存储机制,它应该适用于最广泛的数据类型,并以最低的维护成本(易用性、不易出错)提供尽可能高的性能。到目前为止,SQL 和关联数据库是最好的折衷方案。Google 为其专有数据库开发 BigTable 有其原因,数据最适合这种结构,性能胜过其他因素。使用 BigTable 构建机械零件订购系统可能不是一个好主意。

        IndexedDB 似乎不是一个好的通用数据存储机制。听起来它对使用来说级别太低了。例如,数据完整性完全由用户负责,能够轻松地在一个存储中存储完全不同的数据类型,坦率地说,这让我感到害怕,因为我在过去 30 年里看到过很多这样的开发者。为什么人们认为能够在同一个逻辑数据存储中存储人员和公司是一件好事?

        2011 年 9 月 15 日 14:07

  70. devlim

    用户清除缓存/Cookie 后,数据库是否仍然存在?

    2011 年 7 月 20 日 10:18

    1. 迈克尔

      是的,确实存在。
      IndexedDB 数据存储在不同的位置(在 Chrome 和 FF 中,每个域都有一个专用的文件夹),因此清除缓存和 Cookie 不会影响存储的日期。

      2011 年 9 月 1 日 06:43

      1. Robert Brown

        但是,你也可以清除数据库,如果你不够精通,可能会在清除 Cookie 时意外地清除它。

        2011 年 9 月 15 日 14:08

  71. Ken Corey

    真是太自命不凡了。IndexedDB 代码更复杂,大小差不多或更大,这有点像争论鸡蛋哪一头更容易打开。

    示例 4(WebSQL)任何懂 SQL 的人都能看懂。很明显。
    示例 4(IndexedDB)是一堆乱七八糟的 Javascript。

    他们在想什么?真的有必要这样保护别人的工作吗?

    2011 年 9 月 6 日 13:23

  72. Leigh Harrison

    我有一个现有的桌面应用程序,我想将其重新开发成一个具有离线存储功能的 Web 应用程序。它目前使用 SQLite,拥有 14 个表,并根据用户的选择构建自己的动态查询。许多查询包含多个子查询和深度嵌套的 WHERE 子句。

    我可以毫不费力地将其移植到 Web SQL DB。即使从理论层面上考虑使用 Indexed DB 执行这项任务也几乎不可能。

    在某些情况下,Indexed DB 可能是完全可以接受的解决方案。但它不适合我想要做的一些工作。而且我相信 Web 是应用程序的未来。

    为什么不能两者兼得呢?

    2011 年 9 月 20 日 01:49

    1. Paul

      如果你阅读了支持者的评论,我认为原因很明显。这是政治问题。

      像 Couch 和 Indexed DB(都是 Mozilla 的宠儿)这样的 KVP 数据库的支持者坚持认为,我们需要一个数据库,在处理 TB 级数据时,在读取访问方面具有同样可扩展性——在浏览器环境中。

      他们还坚信,这种性能提升值得放弃关联/SQL 数据库所肩负的责任,例如数据完整性和对聚合函数的原生支持。这些解决方案将这些责任转移给了应用程序开发者,让他们通过严格使用良好的设计模式来处理。作为交换,他们可以声称数据库的 I/O 时间更短,而无需提供任何关于对实际整体应用程序性能影响的指标。

      支持者还坚持认为,阻止 SQL 语言感染 Web 开发还有一个额外的优势……因为当你在处理 Web 时,你不应该被迫同时处理多种语法结构和语言。

      这些支持者可能是对的,但是我没有看到任何关于这些数据库的框架、报表工具或其他开发工具的建议……因为它们不存在。说 Indexed DB 处于起步阶段是轻描淡写了。与 WebDB 相比,WebDB 基于 SQLite,拥有大量开发、报表和测试工具,对于任何真正想要进行实际应用程序开发的人来说,优势是显而易见的……Mozilla 没有支持 WebDB(至少在 Indexed DB 成熟之前)没有任何正当理由,除了政治问题……多项标准可以也应该与离线存储一起支持,就像多种文档布局标准(XML、HTML、XHTML 等)得到支持一样。

      2011 年 9 月 21 日 12:45

      1. 丹尼尔

        我原本不想评论,但你提到没有与 IndexedDB 相关的工具和框架……碰巧我为一个高级 MooTools 库编写了一个,在我看来,它绝对非凡:https://github.com/csuwldcat/mootools-htmlx/blob/master/Source/IndexedDB/Database.js

        使用这个基于 MooTools 的 Database.js 脚本,如果你不想使用异步操作,就不需要担心(它内置了异步 DB 请求的排队功能),你也不必不断地重新生成连接到 DB(它会为你完成),而且你会获得大量可链接的辅助方法,让你可以轻松地使用。哦,我是否提到你可以使用 JSON 对象引导一个模式,如果你喜欢的话?

        怎么样? ;)

        2011 年 9 月 21 日 13:10

        1. Marcelo Cantos

          那么,有没有相当于 sqlite3 CLI 的东西呢?我找到了 Firefox 的附加组件数据库并用 sqlite3 打开了它,输入“.schema”,然后输入“SELECT name FROM addon;”,然后,我看到了一个列表,里面列出了我当前安装的 Firefox 附加组件。现在,这不是 WebSQL,所以我进行了一次进一步的测试……

          我在 Chrome 中加载了 http://project.mahemoff.com/sql.html 并添加了几个城市。然后,我用 sqlite3 加载了相应的数据库,用 .schema 和 SELECT 确认了城市是否存储,用 INSERT 添加了另一个城市,然后重新加载了网页。结果就在那里。整个过程不到一分钟,大部分时间都花在弄清楚 Chrome 将 WebSQL 数据库存储在哪里。

          想想这种灵活性会对开发过程产生多大的影响,尤其是在你从众多现有的 GUI 客户端中选择,而不是使用老旧的 sqlite3 CLI,甚至使用具有 SQLite 绑定的多种语言之一构建你自己的工具时。例如,下面的 Python 脚本从另一个网页中提取城市人口列表,并将它们添加到 http://project.mahemoff.com/sql.html 中的 WebSQL 演示中。重新加载后,演示将显示 100 个城市的的人口。

          $ python -c ‘
          import sqlite3, urllib2, re
          conn = sqlite3.connect(“http_project.mahemoff.com_0/11”)
          conn.executemany(
          “INSERT INTO cities (name, population) VALUES (?, ?)”,
          sorted((city, int(pop.replace(“,”,””)))
          for line in urllib2.urlopen(“http://www.worldatlas.com/citypops.htm”)
          for m in [re.match(r”^s*d+.s+(.+?),.*?([d,]+)”, unicode(line, “utf-8”))]
          if m
          for (city, pop) in [m.groups()]))
          conn.commit()

          我相信很多人都在努力使 IndexedDB 更易于使用。但是当 Paul 说没有工具时,我不认为他指的是 235 行 API 包装器——尽管这些代码行可能很出色。

          2011 年 10 月 22 日 08:11

          1. 丹尼尔

            我不确定你是否真的理解你似乎轻视的“API 包装器”。首先,它不仅仅是一个包装器。它提供了人们在使用 JS 原生对象(如 Array)时习惯使用的便利方法,而这些方法在原生 IndexedDB 对象中并不存在。此外,它完全消除了异步处理,让你永远不必担心你的事务对象是否已过时。

            当你称它为*包装器*并将其轻率地抛弃时,你就暴露了自己的想法。那时我知道你并没有认真地研究它,更别说尝试过它了。;)

            2011 年 10 月 24 日 09:15

          2. Marcelo Cantos

            @Daniel:首先,在评论之前,我确实认真地研究了它,而且不,我称它为包装器并不是想轻视它。即使是原始 SQLite API 也比 C++/Python/Javascript/等包装器更难编码,这些包装器也比仅仅“包装”SQLite API 做得更多。如果我显得轻视,我真诚地道歉;这不是我的本意。

            我的观点,现在仍然是,一个让访问原始 API 变得更容易的库——即使它改进了异步处理并增加了对存储其他数据类型的支持——与 SQLite 提供的广泛的工具、库和服务相比,还差得很远。你是否质疑 Indexed DB 处于起步阶段的说法?这基本上是 Paul 和我所提出的观点。

            2011 年 10 月 24 日 14:46

  73. Mike

    这就是为什么 Firefox 的发展势头正在走下坡路,速度和功能落后于 WebKit。

    http://en.wikipedia.org/wiki/File:Usage_share_of_web_browsers_(Source_StatCounter).svg

    我们选择采取这样的立场:如果用户希望他们的应用程序具有离线功能,那么他们必须使用 WebKit 浏览器或使用 Chrome Frame 的 IE。服务器 DB 和 iOS/Android 应用程序已经在使用 SQL,使用非常相似的数据库模式编写 HTML5 应用程序有很多优势。SQL 几乎适用于所有移动设备和 80% 的桌面浏览器(使用 Google Frame)。

    我的用户没有问题使用更高级的 Web 浏览器来获得离线功能,他们中的大多数人转向 Chrome,而且再也没有回头。

    2011 年 10 月 22 日 12:23

  74. Shiby

    我之前发布过一篇帖子:在我的 Firefox 中运行示例代码时出现异常。但是使用 Trail Tool (http://nparashuram.com/trialtool/index.html#example=/ttd/IndexedDB/ie.html&selected=#prereq&amp;) 在同一个 Firefox 窗口中运行,一切正常。有人可以建议一下可能存在什么问题吗?

    2011 年 10 月 25 日 04:51

  75. […] 这种语法与 SQL 替代方案相比简直糟糕透顶。在 Mozilla Hacks 上找到的代码示例很好地证明了这一点(尽管这篇文章的重点似乎应该是 […])

    2012 年 1 月 29 日 07:13

  76. […] Mozilla Hacks 博客中关于 Web 数据库的几篇文章,IndexedDB 的发展之路,以及 MSDN 对 IndexedDB(在 IE10 中支持)的介绍。MSDN 中还介绍了 WebStorage […]

    2012 年 4 月 1 日 下午 6:21

  77. Fikre

    我总是说“用常识!”。Firefox 正在变得越来越复杂、缓慢和过时。当我看到这种态度说“我们不想支持 webdb,没有令人信服的理由”时,我就明白为什么 Firefox 很快就会成为历史。我认识的许多人现在都在转向 Chrome,因为它易于使用。用户和开发者并不关心政治和一些理论上的废话。他们总是更喜欢一些可以轻松使用的东西。这只是常识。如果你忽视了对任何正常人来说都显而易见的简单事物,那么你就完了!

    2012 年 4 月 14 日 下午 8:53

  78. Stan

    当你处理复杂的数据关系时,IndexedDB 很难实现。尝试连接多个相关数据存储时,最痛苦的是,如果只是 SQL,只需要几个连接就可以完成。对于数据优化,我无法想象你如何利用 CTE 这样的功能。作为 Web 开发人员,我们应该让工具更容易使用,而不是相反。

    2012 年 10 月 16 日 上午 6:07

  79. Kurt

    我创建了使用 IndexedDB 的 HTML5 页面。他们在 Google Chrome 上运行良好。但在 Mozilla Firefox 上运行时,IndexedDB 根本无法正常工作。我使用的是 Firefox 18.0。有人知道为什么吗?有人在任何版本的 Firefox 上成功运行过 IndexedDB 吗?

    2012 年 12 月 11 日 上午 10:28

    1. Robert Nyman

      这有帮助吗?在 IndexedDB 中存储图像和文件

      2012 年 12 月 11 日 下午 12:33

  80. Kurt

    Robert,
    感谢你指引我阅读这篇文章。我正在阅读它,并将我的代码与你文章中的代码进行比较。

    2012 年 12 月 12 日 下午 12:56

  81. JimP

    请耐心听我说完… 这篇文章是有意义的…

    很久以前,我在一家大公司工作,当时我们正在考虑两种竞争的数据库技术。一种基本上是分层数据库管理器,其查询语言类似于 VSAM。另一种是 SQL RDBMS。我们要求两家公司使用我们公司典型的数据实现一系列 CRUD 类型的操作。双方都可以在他们选择的任何方式下构建数据,只要我们要求的操作能够实现。

    SQL 团队创建了一组表,并编写了七个查询,大约花了 3 个小时。分层团队手工生成高度优化的代码来做同样的事情,花了 7 周时间(全职)。

    SQL 团队的每个查询平均耗时约 1.5 秒。
    分层团队的每个查询平均耗时约 0.5 秒。

    分层团队占优势,对吧?但是等等… SQL 团队看了一眼结果,说“好吧,我想我需要创建一两个索引。”一个多小时后,他们将平均查询时间缩短到 0.8 秒。性能仍然落后于分层团队,但用户并没有真正注意到性能差异。

    然后我们要求两家公司对其中一个查询进行相当大的更改。(什么?你从来没有遇到过需求在中途改变的情况吗?)SQL 团队耸耸肩,花了 30 分钟进行更改,并让新版本以与旧版本相似的性能运行。分层团队大发雷霆,花了将近一周时间处理这个问题,最后返回了一个能产生所需结果,但性能非常差的查询… 他们说他们必须重新设计整个套件才能解决这个问题。

    我们公司的决定?我们选择了 SQL。毫无疑问,一个精通编程的人,花大量时间编写高度优化的代码,可以让分层解决方案的性能优于 SQL 数据库。但分层解决方案的开发成本高出 35 倍。而且,一个(非常常见)的需求在中途变更,开发成本大约是原来的 70 倍。

    那么为什么在这个背景下要提起这段“古代历史”?我在这里听到同样的说法:一个优秀的程序员应该能够使用 IndexedDB 编写更快速、更优雅的代码。(这很可能——甚至可能是——真的)。但代价是什么?对于绝大多数“现实世界”的程序员来说,他们属于“平均水平”的技能类别?(让我们面对现实吧,朋友们,所有程序员中有一半的技能水平都“低于平均水平”!想想吧… 向左看,向右看,如果你没有看到坐在那里的“低于平均水平”的程序员,那么你很可能就是那个程序员… ;-) 对于这些人,甚至对于那些真正“高于平均水平”的人来说,WebSQL 可能是更好的商业解决方案。它可能不像那么优雅,但随着时间的推移,编写、维护和更改这些解决方案的成本可能会更低。

    我的投票:提供两种接口,让程序员决定何时“付账”以获得最大的灵活性,以及何时使用“足够好”的解决方案。

    2013 年 3 月 6 日 下午 7:32

  82. Anthony Caudill

    看起来,为我的 Web 应用精通 Chrome 的技术值得付出努力。Moz 在过去几年一直在走下坡路… 我的理论是,当 Blake Ross 接管时,他提升了一些和他在一起的人,他们坚持了一段时间,并恐吓那些对设计一无所知的疯狂包装大师,让他们保持沉默,但现在 Seamonkey 人已经接管了,Moz 又回到了精神病院。这是一个艰难的决定(也许比它应该更艰难),但我会很快放弃 Firefox,转而使用 Google。

    2013 年 3 月 9 日 下午 3:08

  83. Daniel Buchner

    哇,人们似乎忘记了我们已经进入了一个以客户驱动的应用程序为主导的消费环境,这些应用程序不受大型数据库和与后端服务器交互的限制。显然,许多应用程序仍然依赖于这样的模型,但 IndexedDB API 满足了当今常见的移动应用程序用例。

    对于这个帖子中每一个对无法将 SQL 范式转移到客户端而感到愤怒的人,会有十个客户端开发人员,当他们配备了一个精巧的客户端 IndexedDB 模块/库时,他们每天都会很高兴不用处理 SQL。

    感知就是现实,朋友们——你必须意识到,许多为手机、平板电脑和…呃…眼镜开发的应用程序,与老式的服务器绑定应用程序不同。此外,开发人员群体也在发生变化——它现在包括纯 JS 开发人员,他们将开发应用程序,其中几乎所有代码都驻留在已安装的、设备上的软件包中。这些开发人员不太关心遥远的关联数据库服务器或它所存储的数百万行数据。这一点得到了整个类别的授权、内容/媒体、支付和 NoSQL 存储服务的出现所强调,这些服务现在可供那些厌倦了传统应用程序堆栈交互/维护迫使他们经历的所有麻烦的 Web 应用开发人员使用。

    也许对于那些与旧的 Web 开发模式密切相关的人来说,这很令人沮丧,但这是应用程序开发明确发展方向的现实。

    2013 年 3 月 9 日 下午 3:52

    1. Anthony Caudill

      Daniel,为什么不让人们选择呢?让消费者决定。并且请,请让文件句柄 API 成为与 IndexedDB 无关的东西。我们不想要它。我们的用户也不想要它。他们想要可以与其他用户和 PC 之间共享的数据。他们需要在浏览器和文件系统之间进行转换。这对我来说似乎是一堆废话,阻碍了喜欢用 Javascript 编码的人。我喜欢 Javascript… 用它将原型想法变成可行想法太容易了… 你可以从一个目标开始,但可能没有计划,然后继续前进直到你实现目标。也许你的代码与其他脚本不兼容… 但如果你正在创建前所未有的东西,也许它不需要兼容。我很少使用库,但我的代码很轻量级,也很容易理解。这就是我所需要的… 我可以用 Javascript 独自完成用 Java 或 C++ 完成需要十个人完成的事情。再加上能够利用如今 HTML 5 提供的所有浏览器功能… 你用 Java 或 C++ 也无法以同样的简单性做到这一点(VB 是唯一接近的东西)。云服务对小型开发者来说不切实际,因为如果没有花费数千美元,它们就无法管理。

      我个人已经厌倦了。我会转而使用 Chrome。至少他们在那里考虑用户便利性。你可能会赢得我回来,但你必须努力。而且,你必须赢得回你过去两年失去的 8% 的市场份额… 因为他们,我认为离开是可以的。我认为你注定要成为 Web 浏览器的 Linux 桌面:2% 的市场份额,为一小部分隐士般的利基市场而竞争… 让我感到惊讶。…你让我很生气。

      2013 年 3 月 9 日 下午 8:50

      1. Anthony Caudill

        顺便说一下… IndexedDB 有什么问题?为什么这么多人讨厌它?因为它是被拥有影响力的第三方强加于他们的。这与商业数据库的创建者不同。你假设用户会出于品牌忠诚度的原因,迫使开发人员按照你的方式行事。你错了。

        2013 年 3 月 9 日 下午 9:36

  84. DG

    在“云”时代,这个功能无关紧要。Firefox 受困于太多的厨师和糟糕的设计。例如,一些屏幕是类似“about:config”的 URL,而另一些则是老式的弹出式对话框向导,等等… 缺乏 Webkit 兼容性使 Firefox 的引擎处于石器时代… 我讨厌 Chrome,但它是最好的垃圾….

    2013 年 3 月 10 日 下午 5:06

  85. Greg

    我已经很久没有关注这个帖子了,因为它太煽动性了,但抱歉,我必须评论。

    “对于这个帖子中每一个对无法将 SQL 范式转移到客户端而感到愤怒的人,会有十个客户端开发人员,当他们配备了一个精巧的客户端 IndexedDB 模块/库时,他们每天都会很高兴不用处理 SQL。”

    不确定这是否是一个严肃的评论,但我遇到的每个人,无论是客户端还是服务器端开发,都没有遇到过处理 SQL 的问题。此外,作为一个移动开发人员,我放弃 Mozilla 的原因之一是,它对于移动应用程序几乎毫无用处,尤其是因为它不支持 SQLite。今天看到一份报告提到 Firefox 正在避开 iOS——很好。

    正如 Anthony 所说,FireFox 正在(谢天谢地)快速变得无关紧要。

    2013 年 3 月 11 日 上午 6:20

本文的评论已关闭。