javascript - 使用 Dexie 和 Svelte 从 IndexedDB 中检索值

标签 javascript promise svelte indexeddb dexie

我不明白如何使用 Dexie 从 IndexedDB 获取值。数据库在检查工具的“应用程序”选项卡中一切正常。完全新手,所以请理解。

我的 db.js

import Dexie from "dexie";

export const db = new Dexie("myDatabase");
db.version(2).stores({
  history: "++id, daterange, days",
  storage: "id, name, value"
});

db.on("populate", function () {
  db.storage.add({
    id: 0,
    name: "total",
    value: 20
  });
  db.storage.add({
    id: 1,
    name: "left",
    value: 20
  });
});
db.open();

App.svelte

<script>
  import Counter from "./src/Counter.svelte";
  import New from "./src/New.svelte";
  import History from "./src/History.svelte";
  import { liveQuery } from "dexie";
  import { db } from "./src/db";

  let total = liveQuery(() =>
    db.storage
      .where("name")
      .equals("total")
      .value.then(function(a) {
        totals = a;
      })
  );

  let left = 25;
</script>

<style>
  main {
    width: 100%;
  }
</style>

<main>
    <Counter daysLeft={left} daysMax={total}/>
    <New />
    <History />
</main>

无论我尝试什么,对象 daysMax={total} 输出 undefined[object Object] 或类似 [Dexie对象对象]。我只想从 db 中获取 20,如 db.js 中所示:

db.on("populate", function () {
  db.storage.add({
    id: 0,
    name: "total",
    value: 20
  });

(这一切都有效并且在 indexedDb 中可见) 我也试过 daysMax={$total}

CodeSandbox

最佳答案

如您所述,您的数据库设置和初始写入操作已正确完成。问题出在您的查询上:

  let total = liveQuery(() =>
    db.storage
      .where("name")
      .equals("total")
      .value.then(function(a) {
        totals = a;
      })
  );

首先,WhereClause查询的一部分 (db.storage.where("name").equals("total")) 返回 Collection ,引用文档:

Represents a collection of database objects. Note that it will not contain any objects by itself. Instead, it yields a preparation for how to execute a DB query. A query will be executed when calling methods that returns a Promise, such as toArray(), keys(), count() or each().

因此您不能像在代码中那样简单地取消引用 .value。您必须改为使用 Collection 提供的方法之一。由于在您的用例中您只希望在数据库中找到一个匹配项,因此我建议 Collection.first()在这里,它返回一个最终解析为您正在查询的数据的 Promise。

因此您的查询应该如下所示:

  let total = liveQuery(() =>
    db.storage
      .where("name")
      .equals("total")
      .first()
  );

接下来是您使用liveQuery 的方式。什么liveQuery()它所做的是将一个 Promise(您现在将从上一步收到)变成一个 Observable。如文档中所述:

The Svelte Store Contract is a subset of the Ecmascript Observable specification draft which makes the return value of liveQuery() a fully valid Svelte Store by itself.

这里的意思是 total 实际上表现得像 Svelte (readable) store ,可以订阅或使用速记 $ 语法访问。这意味着 $total 将保留 - 一旦查询完成并且 promise 解决 - 与您的查询匹配的数据库对象。

因为它是一个 Observable(因此也是一个 Svelte 存储),对数据库记录所做的任何更新都会立即反射(reflect)在 $total 的值中。

最后要做的是访问数据库对象的 value 属性。 因为 $total 在查询运行和 promise 解析时最初将是 undefined,所以我还要添加一个条件。 为此,我建议使用一个小的响应式声明以保持整洁,选择一个允许您使用简写 prop 表示法的变量名,结合一个条件以仅在查询已解决时显示计数器:

<script>
    // ...your existing script code with updated query...
    $: daysMax = $total?.value // undefined until the query resolves, actual value once the query has resolved
</script>

<main>
    {#if daysMax !== undefined}
        <Counter daysLeft={left} {daysMax} />
    {/if}
    <New />
    <History />
</main>

Forked, working CodeSandbox

关于javascript - 使用 Dexie 和 Svelte 从 IndexedDB 中检索值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71557580/

相关文章:

javascript - 使用 Underscore 将嵌套 JSON 展平为键控值数组

javascript - 如何根据对象的 "blueprints"将给定对象与类别匹配

javascript - JavaScript中 "if (!J || !S)"的含义是什么?

javascript - 错误 : timeout of 2000ms exceeded. 带有 promise 的单元测试

javascript - 外部依赖项在 Nav.svelte 中不起作用

javascript - 在可重用 JavaScript 函数而不是 Svelte 组件中使用 SvelteKit 页面 URL 时未定义

javascript - Fabric js 从来自另一个 url 的数据 uri 加载图像

node.js - NodeJS 中的 Firebase javascript promise

javascript - Firebase .orderByChild().equalTo().once().then() 当 child 不存在时 promise

svelte - 如何更改 Svelte Material UI (@SMUI) slider 标签中的背景?