使用 Dexie 和 Svelte 从 IndexedDB 中检索值
Retrieve value from IndexedDB using Dexie and Svelte
我不明白如何使用 Dexie 从 IndexedDB 获取值。检查工具的 'application' 选项卡中的数据库都很好。完全新手,还请谅解
我的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]
的对象。我只想从数据库中获取 20
,如 db.js:
所示
db.on("populate", function () {
db.storage.add({
id: 0,
name: "total",
value: 20
});
(这一切都有效并且在 indexedDb 中可见)
我也试过daysMax={$total}
如您所述,您的数据库设置和初始写入操作已正确完成。问题出在您的查询上:
let total = liveQuery(() =>
db.storage
.where("name")
.equals("total")
.value.then(function(a) {
totals = a;
})
);
首先,WhereClause part of your query (db.storage.where("name").equals("total")
) returns a 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(),其中 returns 一个最终解析为您正在查询的数据的 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 一样,可以使用 shorthand $
语法订阅或访问。这意味着 $total
将保留 - 一旦查询完成并且承诺解决 - 与您的查询匹配的数据库对象。
而且因为它是一个 Observable(因此也是一个 Svelte 存储),对数据库记录所做的任何更新都会立即反映在 $total
的值中。
最后要做的是访问数据库对象的value
属性。 因为在查询运行和 promise 解析时 $total
最初将是 undefined
,我还要添加一个条件。 为此,我建议使用一个小的响应式声明为了保持整洁,选择一个允许您使用 shorthand 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>
我不明白如何使用 Dexie 从 IndexedDB 获取值。检查工具的 'application' 选项卡中的数据库都很好。完全新手,还请谅解
我的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]
的对象。我只想从数据库中获取 20
,如 db.js:
db.on("populate", function () {
db.storage.add({
id: 0,
name: "total",
value: 20
});
(这一切都有效并且在 indexedDb 中可见)
我也试过daysMax={$total}
如您所述,您的数据库设置和初始写入操作已正确完成。问题出在您的查询上:
let total = liveQuery(() =>
db.storage
.where("name")
.equals("total")
.value.then(function(a) {
totals = a;
})
);
首先,WhereClause part of your query (db.storage.where("name").equals("total")
) returns a 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(),其中 returns 一个最终解析为您正在查询的数据的 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 一样,可以使用 shorthand $
语法订阅或访问。这意味着 $total
将保留 - 一旦查询完成并且承诺解决 - 与您的查询匹配的数据库对象。
而且因为它是一个 Observable(因此也是一个 Svelte 存储),对数据库记录所做的任何更新都会立即反映在 $total
的值中。
最后要做的是访问数据库对象的value
属性。 因为在查询运行和 promise 解析时 为此,我建议使用一个小的响应式声明为了保持整洁,选择一个允许您使用 shorthand prop 表示法的变量名,并结合条件以仅在查询已解决时显示计数器:$total
最初将是 undefined
,我还要添加一个条件。
<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>