Мой первый пост был посвящен подключению svelte store к indexedDB. Этот пост будет обновлением на ту же тему. Продолжайте читать, если вам нужен совершенно другой подход, более практичный в большинстве случаев!
Оглавление
Чего я хочу добиться
Я хочу сохранять данные в indexedDB и использовать их в своем приложении.
Проблема
Поскольку idexedDB работает асинхронно, в большинстве случаев страница загружается раньше данных, что приводит к некрасивому мерцанию при обновлении элементов из-за реактивной природы svelte. Поэтому, по возможности, данные должны загружаться из хранилища, а не из самой indexedDB. Очевидно, что данные должны быть загружены один раз при начальной загрузке страницы — но в SPA это все!
Решение
Маленькое хранилище со специальной функцией, которая получает данные из индексированной базы данных. В принципе, это все, но есть несколько важных тонкостей, которые я объясню через минуту.
Установите Dexie
Для того чтобы использовать это, вам нужно установить Dexie.js:
npm install dexie
Создайте db.js
Это очень минималистичная установка для вашей indexedDB, которая находится в папке lib:
import Dexie from 'dexie';
export const db = new Dexie("user");
db.version(1).stores({
user: "key, value"
});
Создайте stores.js
Это фактический магазин, который вы можете использовать в вашем +page.svelte. Как вы видите, в нем есть функция sync, которая получает данные из индексированной базы данных Dexie и устанавливает данные userData. Она также возвращает обещание, которое будет очень полезно через секунду.
import { writable } from "svelte/store";
import { db } from "$lib/db";
export const userData = writable([]);
userData.sync = function() {
return new Promise (async (resolve, reject) => {
try {
const data = await db.progress.toArray();
userData.set(data);
resolve();
} catch (error) {
console.error(error);
reject (error);
}
})
}
Как загрузить
import { userData } from "@stores"; // I am using an alias here
<script>
function handleMount() {
userData.sync()
}
onMount(handleMount);
</script>
<main>
{#each userData as data}
<p>{data.name}, {data.age}</p>
{/each}
</main>
Выполняйте действия, когда данные загружены
Иногда необходимо дождаться данных, чтобы вызвать функцию. Это больше не проблема, поскольку вы можете просто использовать .then после функции sync-Function.
import { userData } from "@stores"; // I am using an alias here
<script>
function handleMount() {
userData.sync()
.then(() => {
// do stuff!
})
}
onMount(handleMount);
</script>
<main>
{#each userData as data}
<p>{data.name}, {data.age}</p>
{/each}
</main>
Как сохранить
Чтобы сохранить данные в indexedDB, просто используйте Dexie API, а затем обновите хранилище:
function saveData() {
db.user.put({ name, inputValue });
userData.sync()
}
Мне очень нравится этот рабочий процесс, поскольку он дает мне больше контроля, чем предыдущее решение, но при этом остается очень, очень простым!
Ваше здоровье,