Библиотека localForage предоставляет единый асинхронный API поверх различных механизмов хранения браузера (IndexedDB, WebSQL, localStorage). Одной из ключевых возможностей архитектуры является поддержка нескольких независимых экземпляров, позволяющих логически и физически разделять данные внутри одного приложения.
Каждый экземпляр представляет собой изолированную конфигурацию, в которой задаются параметры хранения: имя базы данных, имя хранилища (storeName), предпочтительные драйверы и другие настройки. Это позволяет строить модульные системы хранения без пересечения ключей и без риска коллизий.
По умолчанию библиотека использует глобальный singleton:
Однако при использовании метода создания экземпляра появляется возможность выделить отдельные «контексты хранения»:
Каждый экземпляр работает как автономный слой поверх браузерного storage API.
Основной механизм изоляции реализован через метод
createInstance:
import localForage from "localforage";
const userStore = localForage.createInstance({
name: "app_db",
storeName: "users"
});
const settingsStore = localForage.createInstance({
name: "app_db",
storeName: "settings"
});
name Определяет имя базы данных (в IndexedDB) или namespace для других драйверов.
storeName Логическое разделение внутри одной базы данных. Фактически формирует отдельный object store.
driver Позволяет задать предпочтительный механизм хранения:
driver: localForage.INDEXEDDB
При использовании нескольких экземпляров важно понимать внутреннюю структуру:
Определяет физическую базу IndexedDB:
Каждая база существует независимо.
Внутри одной базы создаются отдельные хранилища:
Каждый store содержит набор ключей:
users:
1 -> { ... }
2 -> { ... }
settings:
theme -> "dark"
Использование нескольких экземпляров особенно эффективно при модульной архитектуре.
const authStorage = localForage.createInstance({
name: "app",
storeName: "auth"
});
const profileStorage = localForage.createInstance({
name: "app",
storeName: "profile"
});
const cacheStorage = localForage.createInstance({
name: "app",
storeName: "cache"
});
Такое разделение позволяет:
Несмотря на логическую изоляцию, драйверы остаются общими для всего приложения. Однако каждый экземпляр может иметь собственный приоритет выбора.
localForage.createInstance({
name: "app",
storeName: "fast_cache",
driver: [
localForage.INDEXEDDB,
localForage.LOCALSTORAGE
]
});
Каждый экземпляр:
При использовании IndexedDB:
name становится именем базы данныхstoreName — именем object storeВажно учитывать:
storeName внутри одной
name используют одну физическую базуname создают полностью независимые базыЭто влияет на:
Типичная архитектура приложения:
Каждый слой изолирован.
const tempCache = localForage.createInstance({
name: "app",
storeName: "temp_cache"
});
Позволяет:
Для SaaS приложений:
function createTenantStorage(tenantId) {
return localForage.createInstance({
name: `tenant_${tenantId}`,
storeName: "data"
});
}
Каждый клиент получает:
Разделение экземпляров по версиям:
const v1Store = localForage.createInstance({
name: "app_v1",
storeName: "data"
});
const v2Store = localForage.createInstance({
name: "app_v2",
storeName: "data"
});
Используется при:
Ключи изолированы только внутри store, но не между экземплярами с одинаковыми параметрами.
const a = localForage.createInstance({
name: "app",
storeName: "data"
});
const b = localForage.createInstance({
name: "app",
storeName: "data"
});
Оба экземпляра:
Каждый экземпляр поддерживает собственные операции очистки:
await cacheStorage.clear();
При этом:
Удаление базы требует внешних IndexedDB API.
Использование нескольких экземпляров влияет на поведение:
Создание множества экземпляров с одинаковыми параметрами не даёт изоляции, но усложняет архитектуру.
Хранение кеша и критичных данных в одном store приводит к:
Без строгих правил:
Практическая структура:
const storage = {
auth: localForage.createInstance({
name: "app",
storeName: "auth"
}),
user: localForage.createInstance({
name: "app",
storeName: "user"
}),
cache: localForage.createInstance({
name: "app",
storeName: "cache"
}),
settings: localForage.createInstance({
name: "app",
storeName: "settings"
})
};
Такая модель обеспечивает:
Каждый экземпляр:
При одновременном создании множества экземпляров рекомендуется учитывать:
Экземпляры можно передавать между модулями без риска нарушения изоляции:
export function saveUser(storage, user) {
return storage.setItem(user.id, user);
}
Это позволяет:
Множественные экземпляры упрощают тестирование:
const testStore = localForage.createInstance({
name: "test_db",
storeName: "unit_test"
});
Такая схема предотвращает утечки данных между тестами.