使用Dexie和Svelte从IndexedDB检索值

ffx8fchx  于 2022-12-09  发布在  IndexedDB
关注(0)|答案(1)|浏览(241)

我不明白如何使用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 object Object]的内容。我只想从db中获取20,如db.js中所示:

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

(This所有工作,并在indexedDb中可见)我还尝试了daysMax={$total}
CodeSandbox

46qrfjad

46qrfjad1#

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

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

首先,查询(db.storage.where("name").equals("total"))的WhereClause部分返回Collection,引用文档中的话:
表示数据库对象的集合。请注意,它本身不会包含任何对象。相反,它会产生如何执行DB查询的准备。当呼叫传回Promise的方法(例如toArray()、keys()、count()或each())时,就会执行查询。
因此,您不能像在代码中那样简单地解引用.value,而必须使用Collection提供的方法之一。由于在您的用例中,您只希望在数据库中找到一个匹配项,因此我建议使用Collection.first(),它返回一个Promise,最终解析为您正在查询的数据。
因此,您的查询应改为如下所示:

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

接下来是使用liveQuery的方法,liveQuery()的作用是将一个Promise(你将从上一步得到)转化为Observable,如文档中所述:
Svelte Store契约是Ecmascript Observable规范草案的子集,它使liveQuery()的返回值本身成为完全有效的Svelte Store。
这意味着total实际上就像一个Svelte(可读)存储,可以订阅,也可以用简写的$语法访问,这意味着$total将保存--一旦查询完成并且promise解析--与您的查询匹配的数据库对象。
因为它是一个Observable(因此是一个Svelte存储),所以对数据库记录所做的任何更新都会立即反映在$total的值中。
最后要做的事情是访问数据库对象的value属性。因为$total在查询运行和promise解析时最初是undefined,所以我还要添加一个条件。为此,我建议使用一个小的React式声明来保持整洁,选择一个允许您使用速记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

相关问题